Share
Embed
Transcript
21 slides
-
Agenda 最新のPostgreSQL 18でUUID v7が標準関数として導入 UUIDは主キーに向いている? UUID v4は性能に課題があるとされる UUID v7で改善するらしい [デモ]
インデックスの内部の動作の違いを可視化してみる PostgreSQL 18で考えるUUID主キー -
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主キー -
UUIDとは Universally Unique Identifier どこで誰が生成しても、重複が事実上ほぼ発生しないID 019f55b0-69ab-7f6e-907f-d3c0d448b852 分散システムなどで重宝する 推測困難性を利用するためにも用いられる IDが予測しやすいと総当り攻撃などのリスクが上がる https://example.com/app/users/02
https://example.com/app/users/03 ※ UUIDで完全に攻撃を防げるわけではない PostgreSQL 18で考えるUUID主キー -
UUIDはDBの主キーとしてそのまま使えるのか 観点 bigint identity キー幅 8 bytes 16 bytes 生成場所
DB中心 DB/アプリ 外部公開 推測されやすい 推測されにくい 挿入順 ほぼ単調増加 v4: ランダム / v7: 時刻順 主な価値 DB効率 分散生成・統合 PostgreSQL 18で考えるUUID主キー UUID -
UUID v4はランダム、 UUID v7は時刻順に近い UUID v4 UUID v7 基本はランダム 先頭にUnix
epochミリ秒 生成時刻を持たない 時刻順に近く並ぶ 推測困難性が高い DBのキー順に局所性が出る DBのキー順は散る 作成時刻の露出には注意 PostgreSQL 18で考えるUUID主キー -
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 -
PostgreSQLの主キー B-treeではleaf pageが観測単位になる root INSERT時の流れ internal internal internal internal internal
キーが入るleaf pageを探す 空いていれば追加する 満杯ならsplitする 1つのleaf pageに複数のインデックス情報が格納される ※ デフォルトで8kB PostgreSQL 18で考えるUUID主キー -
leaf pageへのアクセスが増えると性能に響きやすい キャッシュ効率 dirty page index size 局所性 拡散 肥大化
同じページを触るほど共 有バッファに残りやすい 広範囲を少しずつ汚すと 書き戻し対象も散る 分割と空き領域が増える と同じ行数でも大きくな る PostgreSQL 18で考えるUUID主キー -
デモ: pageinspectでleaf pageを定点観測 PostgreSQL 18.4 / Docker uuidv4() と uuidv7()
の2テーブル 50,000行、1,000行ごとにスナップショット pageinspectのbt_page_stats()でページ情報を取得 PostgreSQL 18で考えるUUID主キー -
実測では 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主キー -
v4は散る、 v7は右端に寄る UUID v4 UUID v7 既存leaf pageの広い範囲が変化 leaf densityが下がる
index sizeが大きくなる 右端付近の少数leaf pageに集中 leaf densityが高い index sizeが小さくなりやすい 大規模化するとキャッシュ効 率に響きやすい UUIDの利便性とB-tree局所性を 両立しやすい PostgreSQL 18で考えるUUID主キー -
結論: UUID v7は主キー候補として現実的な選択肢 採用しやすい UUIDを主キー・公開IDにしたい DB外でIDを生成したい UUID v4のランダム挿入が気になる 生成時刻の露出を許容できる 慎重に見る
DB性能とサイズ効率が必要 FK/JOINが非常に多い 生成時刻の露出が問題 単一DB中心ならbigint、UUIDが必要ならv7を第一候補にする。 PostgreSQL 18で考えるUUID主キー -
APPENDIX 補足: 検証用テーブル定義 CREATE UNLOGGED TABLE v7_events ( id uuid
PRIMARY KEY DEFAULT uuidv7(), insert_no bigint NOT NULL, payload text NOT NULL ); PostgreSQL 18で考えるUUID主キー -
APPENDIX 補足: pageinspectで見ているもの 列 意味 デモでの用途 blkno 物理ブロック番号 ページ識別 live_items
ページ内アイテム数 変化検知 free_size 空き領域 充填率 btpo_prev / next leaf pageリンク B-tree論理順 PostgreSQL 18で考えるUUID主キー -
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主キー