sequential_uuid 拡張機能は、シーケンシャルパターンを作成する 2 つの UUID ジェネレーターを提供します。これにより、完全にランダムな UUID によって引き起こされるランダム I/O の問題を軽減できます。
適用範囲
以下のバージョンの PolarDB for PostgreSQL がサポートされています:
PostgreSQL 18 (マイナーエンジンバージョン 2.0.18.1.2.0 以降)
PostgreSQL 17 (マイナーエンジンバージョン 2.0.17.6.4.0 以降)
PostgreSQL 16 (マイナーエンジンバージョン 2.0.16.9.9.0 以降)
PostgreSQL 15 (マイナーエンジンバージョン 2.0.15.14.6.0 以降)
PostgreSQL 14 (マイナーエンジンバージョン 2.0.14.5.1.0 以降)
PostgreSQL 11 (マイナーエンジンバージョン 2.0.11.9.28.0 以降)
コンソールで、または SHOW polardb_version; 文を実行することで、マイナーエンジンバージョン番号を表示できます。マイナーエンジンバージョンの要件が満たされていない場合は、マイナーエンジンバージョンをアップグレードする必要があります。
背景情報
標準のランダム UUID ジェネレーターは、指定された範囲から値を均一に選択します。これにより、すべてのインデックスリーフページが等しくヒットする可能性があるため、インデックスにデータを挿入する際のデータ局所性が低下します。これにより、インデックス全体がメモリに強制的に読み込まれる可能性があります。これは、小さいインデックスでは問題になりません。しかし、インデックスサイズが共有バッファーまたは RAM サイズを超えると、キャッシュヒット率は急速に低下します。
ランダムな UUID と比較して、シーケンスとタイムスタンプに基づく UUID はシーケンシャルパターンを持ちます。このパターンにより、新しいシーケンス値は以前の値よりも大きく、タイムスタンプは単調増加するため、新しいデータはほぼ常にインデックスの右端に挿入されます。これにより、キャッシュヒット率の向上に役立ちます。
シーケンシャルパターンを持つ UUID ジェネレーターは、UUID の予測可能性とマシン間の衝突の確率を高めます。
詳細については、「Sequential UUID Generators」をご参照ください。
sequential_uuid の主な目的は、ランダム性を大幅に低下させることなく、よりシーケンシャルな UUID を生成することです。ランダム性が低下すると、衝突の確率と UUID の予測可能性が高まる可能性があります。
ジェネレーターの設計
UUID をよりシーケンシャルにする最も簡単な方法は、シーケンシャルな値をプレフィックスとして使用することです。たとえば、シーケンスまたはタイムスタンプから値を取得し、ランダムなデータを追加して 16 バイトの UUID を形成できます。このメソッドは、ほぼ完全にシーケンシャルな UUID を生成しますが、2 つの問題があります:
ランダム性の低下:`bigint` 値を生成するシーケンスを使用する場合、UUID のランダム部分は 16 バイトから 8 バイトに減少します。タイムスタンプも、その精度に応じて同様の方法でランダム性を低下させます。このランダム性の低下は、衝突の確率と UUID の予測可能性を高めます。たとえば、どの UUID が時間的に近接して生成されたかを判断したり、特定のタイムスタンプを推測したりすることもできます。
肥大化:値が単調に増加する場合、既存データが削除された後にインデックスが肥大化する可能性があります。ログテーブル内のタイムスタンプに対するインデックスが一般的な例です。
これらの問題を解決するために、`sequential_uuid` ジェネレーターは定期的にループバックするように設計されています。ループバックは、設定された数の UUID が生成された後、または特定の時間間隔の後に発生する可能性があります。どちらの場合も、UUID は (ブロック ID; ランダムデータ) のフォーマットでブロック単位で生成されます。ブロック ID のサイズは固定されており、ジェネレーターのパラメーターであるブロック数に依存します。たとえば、デフォルトの 65,536 ブロックを使用する場合、ブロック ID には 2 バイトが必要です。ブロック ID は各ブロックで増加し、最終的にループバックします。
シーケンスベースの UUID ジェネレーターは、それぞれ 256 個の UUID を含むブロックを使用できます。2 バイトのブロック ID は次のように計算されます:
(nextval('s') / 256) % 65536説明ジェネレーターは、16,777,216 (256 × 65,536) 個の UUID が生成されるたびにループバックします。
ブロックサイズは、それに含まれる UUID の数によって定義されます。
タイムスタンプベースの UUID ジェネレーターは、シーケンスベースのジェネレーターと同じく、デフォルトで 65,536 ブロックを持ちます。ブロック ID は次のように計算されます:
(timestamp / 60) % 65536説明ジェネレーターは約 45 日ごとにループバックします。
ブロックサイズは時間間隔として定義されます。デフォルト値は 60 秒です。
UUID 生成関数
sequential_uuid 拡張機能は、シーケンシャルパターンを持つ UUID を生成する 2 つの関数を提供します。1 つはシーケンスを使用し、もう 1 つはタイムスタンプを使用します。
uuid_sequence_nextval 関数は、次のパラメーターを受け入れます:
`regclass` 型のシーケンスオブジェクト。
ブロックサイズを整数で指定します。デフォルト値は 65536 です。
ブロック数を示す整数 (デフォルト:65536)。
シーケンスを使用してシーケンシャルパターンを持つ UUID を生成します:
CREATE EXTENSION sequential_uuids; CREATE SEQUENCE s; SELECT uuid_sequence_nextval('s'::regclass, 256, 65536);結果は次のようになります:
uuid_sequence_nextval -------------------------------------- 00005547-8a67-452d-bdf7-b390f1edc49b (1 row)uuid_time_nextval 関数は、次のパラメーターを受け入れます:
秒単位の時間間隔を示す整数 (デフォルト:60)。
ブロック数を示す整数 (デフォルト:65536)。
タイムスタンプを使用してシーケンシャルパターンを持つ UUID を生成します:
CREATE EXTENSION sequential_uuids; SELECT uuid_time_nextval(1, 256);次の結果が返されます:
uuid_time_nextval -------------------------------------- 08dac705-8776-4ce3-a45c-123fd65e11e8 (1 row)
これらのパラメーターのデフォルト値は、ほとんどのシナリオに適しています。