Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PostgreSQL 18で考えるUUID主キー

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

PostgreSQL 18で考えるUUID主キー

Avatar for Kazuhiro Seo

Kazuhiro Seo

July 26, 2026

More Decks by Kazuhiro Seo

Other Decks in Programming

Transcript

  1. PostgreSQL 18でUUID v7が標準関数になった select uuidv4(); select uuidv7(); -- UUIDからtimestampを抽出 select

    uuid_extract_timestamp(uuidv7()); -- UUIDからversionを抽出 select uuid_extract_version(uuidv7()); PostgreSQL 18で考えるUUID主キー
  2. UUIDはDBの主キーとしてそのまま使えるのか 観点 bigint identity キー幅 8 bytes 16 bytes 生成場所

    DB中心 DB/アプリ 外部公開 推測されやすい 推測されにくい 挿入順 ほぼ単調増加 v4: ランダム / v7: 時刻順 主な価値 DB効率 分散生成・統合 PostgreSQL 18で考えるUUID主キー UUID
  3. UUID v4はランダム、 UUID v7は時刻順に近い UUID v4 UUID v7 基本はランダム 先頭にUnix

    epochミリ秒 生成時刻を持たない 時刻順に近く並ぶ 推測困難性が高い DBのキー順に局所性が出る DBのキー順は散る 作成時刻の露出には注意 PostgreSQL 18で考えるUUID主キー
  4. UUID v7は先頭48bitにUnix epochミリ秒を持つ unix_ts_ms 48 bits ver 4 rand_a 12

    bits var 2 先頭が時刻なので、 B-treeのキー順として 「新しい IDほど右側」に寄りやすい PostgreSQL 18で考えるUUID主キー rand_b 62 bits
  5. PostgreSQLの主キー B-treeではleaf pageが観測単位になる root INSERT時の流れ internal internal internal internal internal

    キーが入るleaf pageを探す 空いていれば追加する 満杯ならsplitする 1つのleaf pageに複数のインデックス情報が格納される ※ デフォルトで8kB PostgreSQL 18で考えるUUID主キー
  6. leaf pageへのアクセスが増えると性能に響きやすい キャッシュ効率 dirty page index size 局所性 拡散 肥大化

    同じページを触るほど共 有バッファに残りやすい 広範囲を少しずつ汚すと 書き戻し対象も散る 分割と空き領域が増える と同じ行数でも大きくな る PostgreSQL 18で考えるUUID主キー
  7. デモ: pageinspectでleaf pageを定点観測 PostgreSQL 18.4 / Docker uuidv4() と uuidv7()

    の2テーブル 50,000行、1,000行ごとにスナップショット pageinspectのbt_page_stats()でページ情報を取得 PostgreSQL 18で考えるUUID主キー
  8. 実測では v7が触るleaf pageはかなり少なかった 指標 UUID v4 UUID v7 平均 更新ページ数

    / 回 126.92 4.82 最大 更新ページ数 / 回 266 5 leaf page数 276 192 平均 充填率 62.80% 89.89% インデックスサイズ 2.17 MiB 1.52 MiB レコード数 / 秒 510k 559k このデモでは、 v7は右端付近の数ページだけを触り続けた PostgreSQL 18で考えるUUID主キー
  9. v4は散る、 v7は右端に寄る UUID v4 UUID v7 既存leaf pageの広い範囲が変化 leaf densityが下がる

    index sizeが大きくなる 右端付近の少数leaf pageに集中 leaf densityが高い index sizeが小さくなりやすい 大規模化するとキャッシュ効 率に響きやすい UUIDの利便性とB-tree局所性を 両立しやすい PostgreSQL 18で考えるUUID主キー
  10. 結論: UUID v7は主キー候補として現実的な選択肢 採用しやすい UUIDを主キー・公開IDにしたい DB外でIDを生成したい UUID v4のランダム挿入が気になる 生成時刻の露出を許容できる 慎重に見る

    DB性能とサイズ効率が必要 FK/JOINが非常に多い 生成時刻の露出が問題 単一DB中心ならbigint、UUIDが必要ならv7を第一候補にする。 PostgreSQL 18で考えるUUID主キー
  11. APPENDIX 補足: 検証用テーブル定義 CREATE UNLOGGED TABLE v7_events ( id uuid

    PRIMARY KEY DEFAULT uuidv7(), insert_no bigint NOT NULL, payload text NOT NULL ); PostgreSQL 18で考えるUUID主キー
  12. APPENDIX 補足: pageinspectで見ているもの 列 意味 デモでの用途 blkno 物理ブロック番号 ページ識別 live_items

    ページ内アイテム数 変化検知 free_size 空き領域 充填率 btpo_prev / next leaf pageリンク B-tree論理順 PostgreSQL 18で考えるUUID主キー
  13. REFERENCES 参考資料 PostgreSQL 18 Documentation: UUID Functions RFC 9562: Universally

    Unique IDentifiers PostgreSQL Documentation: pageinspect https://www.postgresql.org/docs/18/functions-uuid.html https://www.rfc-editor.org/rfc/rfc9562.html https://www.postgresql.org/docs/current/pageinspect.html PostgreSQL 18で考えるUUID主キー