- PostgreSQL 18ではUUIDv7を標準サポートし、ソート可能でインデックスに適した一意識別子を提供
- UUIDv7は、従来のUUIDが持つ分散環境での一意性と安全性を維持しつつ、btreeインデックスに有利な時間ベースのソート構造を採用
- 従来のUUID利用の欠点だったソート不能、インデックスの非局所性、メモリサイズのうち前二者を解決し、時系列ソートと挿入最適化を実現
- PostgreSQL 18では
uuidv7()関数でUUIDを生成でき、タイムスタンプ抽出とカスタム時刻入力機能も提供
- これにより、UUIDを主キーとして使うことをためらっていた理由が解消され、分散システムやマルチテナント環境でより適した選択肢となる
PostgreSQL 18
- PostgreSQL 18のベータ版が公開され、9月の正式リリースを目標にテストが進行中
- 主な機能:
- Async I/O:
io_uringベースの非同期入出力により、シーケンシャルスキャンとvacuumが2〜3倍高速化
- 複数カラムbtreeインデックスのSkip scan、
OR/INクエリ最適化
- アップグレード間でのプランナー統計の維持
- UUIDv7関数
- 仮想生成カラム、OAuthログイン、EXPLAINへのI/O/CPU/WAL情報追加 など
UUIDの利点
- 分散環境で一意なIDを生成できる
- 予測困難な公開識別子として安全性を強化
- クライアント側で直接ID生成でき、サーバー通信を最小化
従来のUUIDの欠点
- ソートできない
- インデックスの非局所性による挿入性能の低下
- 128ビットサイズによるオーバーヘッド
UUIDv7の解決策
- RFC 9562(2024年5月公開) に基づいて導入された新しいUUIDバージョン
- 先頭48ビットにUnix Epochベースのタイムスタンプ、残りに乱数値 + カウンターを組み合わせる
- 時系列順にソート可能で、インデックス挿入効率が向上
- UUIDv6は下位互換向け、UUIDv8は実験用/ベンダー拡張向け
- UUIDv7だけが実質的に意味のある新標準
PostgreSQL 18でのUUIDv7利用
uuidv7()関数で現在時刻ベースのUUIDを生成
uuidv7(INTERVAL)で任意の時間オフセットを反映可能
uuid_extract_version()、uuid_extract_timestamp()関数でUUIDバージョンと生成時刻を抽出可能
- 例:
CREATE TABLE test (
id uuid DEFAULT uuidv7() PRIMARY KEY,
name text
);
INSERT INTO test (name) VALUES ('foo');
INSERT INTO test (name) VALUES ('bar');
INSERT INTO test (id, name) VALUES (uuidv7(INTERVAL '-1 hour'), 'oldest');
SELECT uuid_extract_timestamp(id), name FROM test ORDER BY id;
uuidv4()はgen_random_uuid()のエイリアスとして追加
結論と推奨事項
- UUIDv7は従来のUUID利用時に性能問題を抱えていたユーザーに適している
- ソート性とインデックス性能を確保しながらUUIDの利点を維持
- PostgreSQL 18ベータで今すぐテスト可能
- 分散システム、マルチテナントアプリ、サーバーレス環境でのID生成に適した選択肢
> 「UUIDv7は静かだが強力な機能追加であり、PostgresでUUIDを主キーとして使うことを再考させる」
4件のコメント
私は代わりに Prisma + ULID を使っています。ずっと短くて良いです。
uuid_generate_v7()のような関数を作って使っていたので、うれしいニュースですね。おお!!
おお…!