データベース設計では、MySQL の AUTO_INCREMENT のように、テーブルの各行に一意の識別子を生成することが一般的に求められます。PolarDB for PostgreSQL 分散版では、この機能はシーケンスオブジェクトによって実装されており、SERIAL や BIGSERIAL などの型を介して便利に使用できます。しかし、分散環境では、すべてのノードで生成された ID がグローバルに一意であることを保証することは課題です。PolarDB はこの目的のためにさまざまな実装メカニズムを提供しており、選択するシーケンスの型、主にその整数サイズによって、動作や制限が異なります。
シーケンスの型による違い
分散テーブルのシーケンスの型を選択する前に、以下の表で主な違いを理解し、技術的に適切な判断をしてください。
機能 | 64 ビットシーケンス ( | 16 ビット / 32 ビットシーケンス ( |
推奨用途 | すべての分散テーブルに強く推奨します。 | 制限事項を許容できる場合を除き、分散テーブルには推奨しません。 |
実装 | 分散生成:ID は | 集中生成:ID 生成リクエストをプライマリコンピューティングノード (プライマリ CN) にルーティングする必要があります。 |
ID 生成 | - 任意のコンピューティングノード (CN) で生成可能です。 - グローバルに一意ですが、連続性は保証されません。 | - プライマリ CN でのみ生成可能です。 - プライマリ CN で生成された場合は連続します。 |
主な制限事項 | 生成される ID 値は、生成元のノードに応じて大きな間隔が生じる可能性があります。 | プライマリ CN 以外のノードで ID を生成しようとするとエラーが発生します。 |
分散テーブルには、分散テーブル、レプリケートテーブル、メタデータ管理に追加されたローカルテーブル、および分散スキーマ下のすべてのテーブルが含まれます。すべてのコンピューティングノードに接続し、列値を自動生成する書き込みを実行する必要がある場合は、分散操作 (create_distributed_table など) を実行する前に、すべての自動採番列が bigserial 型であることを確認してください。
詳細な動作と例
64 ビットシーケンス
これは、分散テーブルに一意の ID を生成するために推奨される方法です。
仕組み
すべてのノードで安全に ID を生成するため、PolarDB for PostgreSQL Distributed Edition は 64 ビットの整数空間を分割します。上位 16 ビットは現在のノードの一意の ID を埋め込むために使用され、下位 48 ビットはそのノードの増分シーケンス値に使用されます。この構造は、異なるノードで生成された ID が競合しないことを根本的に保証します。
動作分析
-
利点:任意のコンピューティングノード (プライマリ CN またはセカンダリ 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 ('田中一郎'); -- id: 1
INSERT INTO student (name) VALUES ('鈴木次郎'); -- id: 2 (連続)
-- (セカンダリ CN に切り替え) 別の行を挿入
INSERT INTO student (name) VALUES ('佐藤三郎'); -- id: 281474976710657 (大きな飛び)
-- 結果を表示
=> SELECT * FROM student ORDER BY id;
id | name
-------------------+---------
1 | 田中一郎
2 | 鈴木次郎
281474976710657 | 佐藤三郎
(3 rows)
ID 281474976710657 は巨大な数値に見えますが、そのバイナリ表現を見ると、その構造が明らかになります。0000000000000001 (ノード ID) + 000...0001 (シーケンス値) であり、ノード 1 で生成された最初の ID を意味します。
16 ビット / 32 ビットシーケンス
整数空間が限られているため、これらの型では分散生成を可能にするノード ID を埋め込むことができません。そのため、集中生成戦略を使用します。
仕組み
グローバルな一意性を保証するために、32 ビット / 16 ビットシーケンスのすべての ID 生成リクエストを、プライマリコンピューティングノード (プライマリ CN) にルーティングして処理する必要があります。
動作分析
-
利点:プライマリ CN で生成される ID は連続しており、スタンドアロンデータベースの動作と一致します。
-
制限事項: プライマリ 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 row)
-- (セカンダリ CN に切り替え) データを挿入 — 失敗
INSERT INTO animal (name) VALUES ('dog');
ERROR: nextval(sequence) calls in worker nodes are not supported for column defaults of type int or smallint
HINT: If the command was issued from a worker node, try issuing it from the coordinator node instead.
エラーメッセージは、int または smallint 型の列のデフォルト値に対する nextval (つまり、シーケンス値の生成) の呼び出しが、ワーカーノード (この場合はセカンダリ CN) ではサポートされていないことを明確に示しています。
まとめとベストプラクティス
-
BIGSERIALを優先:分散テーブルの自動採番 ID を設計する際は、常にBIGSERIALまたはBIGINTベースのIDENTITY列を優先してください。 -
BIGSERIALを使用する場合、ビジネスロジックは厳密な ID の連続性に依存すべきではありません。ID の一意性と単調増加 (単一ノード内) は保証されます。 -
SERIALは慎重に使用:ビジネスシナリオがすべての書き込み操作がプライマリ CN を経由することを完全に許容でき、セカンダリ CN からの書き込み可用性を必要としない場合にのみ、SERIALまたはSMALLSERIALの使用を検討してください。