テーブル内の各行に一意の識別子を生成することは、データベース設計における一般的な要件であり、MySQL の AUTO_INCREMENT 機能に似ています。PolarDB for PostgreSQL 分散版では、SERIAL や BIGSERIAL などの型のシーケンスオブジェクトを使用してこの機能を実現できます。しかし、分散環境では、すべてのノードで生成される ID がグローバルに一意であることを保証することが課題となります。PolarDB は、この課題に対処するためにさまざまな実装メカニズムを提供しています。これらのメカニズムの動作と制限は、選択したシーケンスの型によって異なり、これは主にその整数サイズによって決まります。
シーケンス型の違い
分散テーブルのシーケンス型を選択する前に、次の表で主な違いを確認して、情報に基づいた決定を行ってください。
属性 | 64 ビットシーケンス ( | 16 ビット/32 ビットシーケンス ( |
推奨される使用方法 | すべての分散テーブルに強く推奨されます。 | 制限を受け入れることができる場合を除き、分散テーブルには推奨されません。 |
実装 | 分散生成: ID は | 集中生成: ID 生成リクエストは、プライマリ計算ノード (プライマリ CN) にルーティングする必要があります。 |
ID 生成 | - 任意の計算ノード (CN) で生成できます。 - グローバルに一意ですが、連続していることは保証されません。 | - プライマリ CN でのみ生成できます。 - プライマリ CN で生成された場合は連続しています。 |
主な制限事項 | 生成された ID 値は、異なるソースノードで生成されると大きなギャップが生じます。 | プライマリ CN 以外のノードで ID を生成しようとすると、エラーが発生します。 |
詳細な動作と例
64 ビットシーケンス
これは、分散テーブルの一意の ID を生成するための推奨される方法です。
仕組み
すべてのノードで安全に ID を生成するために、PolarDB for PostgreSQL 分散版は 64 ビットの整数空間を分割します。上位 16 ビットには、現在のノードの一意の ID が埋め込まれます。下位 48 ビットは、そのノードの増分シーケンス値に使用されます。この構造により、異なるノードから生成された ID が競合することはありません。
動作分析
利点: プライマリまたはセカンダリ CN などの任意の計算ノードで
INSERT操作を実行できます。これにより、高可用性と高スループットが実現します。注: ID にはノード情報が含まれているため、異なるノードにデータを挿入すると ID 値が大きくジャンプします。値は数値的に連続していません。
例
-- BIGSERIAL を使用する分散テーブルを作成
CREATE TABLE student (id BIGSERIAL, name TEXT);
SELECT create_distributed_table('student', 'id');
-- (プライマリ CN に接続) 2 行のデータを挿入
INSERT INTO student (name) VALUES ('Alice'); -- id: 1
INSERT INTO student (name) VALUES ('Bob'); -- id: 2 (連続)
-- (セカンダリ CN に接続を切り替え) 別の行のデータを挿入
INSERT INTO student (name) VALUES ('Charlie'); -- id: 281474976710657 (ジャンプが発生)
-- 結果を表示
=> SELECT * FROM student ORDER BY id;
id | name
-------------------+---------
1 | Alice
2 | Bob
281474976710657 | Charlie
(3 行)ID 281474976710657 は非常に大きな数値に見えます。そのバイナリ表現は、その構造を明らかにします: 16 ビットのノード ID (0000000000000001) の後に 48 ビットのシーケンス値 (000...0001) が続きます。これは、ノード 1 で生成された最初の ID を表します。
16 ビット/32 ビットシーケンス
整数空間が限られているため、これらの型は分散生成のためにノード ID を埋め込むことができません。そのため、集中生成戦略を使用します。
仕組み
グローバルな一意性を確保するために、16 ビットまたは 32 ビットシーケンスのすべての ID 生成リクエストは、プライマリ計算ノード (プライマリ CN) にルーティングされ、処理される必要があります。
動作分析
利点: プライマリ CN で生成された ID は連続しています。これは、スタンドアロンデータベースの動作と一致します。
制限: セカンダリ CN やデータノード (DN) など、プライマリ CN 以外のノードで ID 生成をトリガーする
INSERT操作を実行することはできません。この操作により、operation is not allowed on this nodeエラーが発生します。
例
-- SERIAL を使用する分散テーブルを作成
CREATE TABLE animal (id SERIAL, name TEXT);
SELECT create_distributed_table('animal', 'id');
-- (プライマリ CN に接続) データを挿入します。操作は成功します。
INSERT INTO animal (name) VALUES ('cat'); -- id: 1
SELECT * FROM animal;
id | name
----+------
1 | cat
(1 行)
-- (セカンダリ CN に接続を切り替え) データを挿入しようとします。操作は失敗します。
INSERT INTO animal (name) VALUES ('dog');
ERROR: ワーカーノードでの nextval(sequence) の呼び出しは、int または smallint 型の列のデフォルトではサポートされていません
HINT: コマンドがワーカーノードから発行された場合は、代わりにコーディネーターノードから発行してみてください。エラーメッセージは、セカンダリ CN などのワーカーノードでは、nextval (シーケンス値を生成するため) を int または smallint 列に対して呼び出すことがサポートされていないことを明確に示しています。
概要とベストプラクティス
常に
BIGSERIALを使用してください。分散テーブルの自動増分 ID を設計する場合は、BIGSERIALまたはBIGINTに基づくIDENTITY列を選択してください。非連続 ID を受け入れます。
BIGSERIALを使用する場合、ビジネスロジックは厳密に連続した ID に依存してはなりません。ID の一意性と単調増加は、単一ノード上で保証されます。SERIALは注意して使用してください。SERIALまたはSMALLSERIALは、ビジネスシナリオがプライマリ CN を介してルーティングされるすべての書き込み操作を許容でき、セカンダリ CN での書き込み可用性が問題にならない場合にのみ使用してください。