テーブルにプライマリキー (PK) を設定することで、各レコードの重複なし(一意性)を保証し、データ整合性を維持するとともに、データ管理を簡素化できます。Hologres におけるプライマリキーは、従来型データベースと同様の属性を持ちます。これは、テーブル内のレコードを一意に識別するための識別子です。プライマリキーとして設定されたフィールドは、すべて一意であり、NULL 値を許容しません。また、複数のフィールドを組み合わせた複合プライマリキーとしても設定可能です。本トピックでは、Hologres におけるテーブルへのプライマリキー設定方法について説明します。
概要
Hologres では、システムが基盤となるストレージレイヤー内でプライマリキーインデックスファイルを自動的に管理します。このファイルはローストア構造を採用しており、高速なキーバリュー (KV) サービスを提供します。インデックスファイル内のキーはテーブルのプライマリキー (PK) であり、値には Row Identifier (RID)(旧称:`unique_id`)およびクラスタリングキーが含まれます。RID は自動生成され、UPSERT 操作ごとに単調増加します。プライマリキーインデックスファイルにより、効率的なプライマリキー競合検出が可能となり、データファイルの位置特定を支援します。テーブルに PK が設定されている場合、プライマリキーインデックスファイルから迅速に RID およびクラスタリングキーを特定できます。その後、これらの情報を用いて対応するデータファイルを特定できます。
Hologres におけるプライマリキーの設定は、リアルタイムデータウェアハウスのさまざまなユースケースに対応するうえで有効です:
高性能な UPSERT および DELETE 操作をサポートします。
従来型データベースの高パフォーマンスな追記専用書き込み機能に加え、Hologres ではプライマリキーを活用して、全行または特定カラムに対する高性能な更新処理を実現します。書き込み更新を行う際、システムは全表スキャンを実行せず、プライマリキーに基づいてレコードを更新します。これにより、高性能な UPSERT 操作が実現され、データの一意性も保証されます。
プライマリキーに基づく高 QPS クエリをサポートします。
「テーブルのストレージフォーマット:列指向、行指向、およびハイブリッド行列表」で説明したとおり、プライマリキーが設定されたテーブルでは、プライマリキーに基づいて全行を迅速に特定できます。これにより、クエリパフォーマンスが向上し、特にプライマリキーがデフォルトでクラスタリングキーおよびディストリビューションキーとなる行指向テーブルにおいて顕著な効果を発揮します。プライマリキーを用いてデータファイルを特定することで、超高速なポイントクエリ(秒間クエリ数 (QPS) が極めて高く、レイテンシがミリ秒単位)を実現でき、リアルタイムリスク管理やリアルタイムレコメンデーションなどのオンラインアプリケーションのユースケースに適しています。
使用上の推奨事項
プライマリキーを設定する際は、業務的な意味を持つフィールドを選択してください。`SERIAL` 型のフィールドをプライマリキーとして使用しないでください。これは、`SERIAL` 型は書き込み時にテーブルロックを使用するため、パフォーマンスが低下するためです。さらに、データ量の増加に伴い、`SERIAL` 型は容易にオーバーフローする可能性があります。
制限事項
プライマリキーは、一意かつ NULL を許容しないカラム、またはその組み合わせである必要があります。複合プライマリキーは、単一の文で設定する必要があります。
複合プライマリキーは最大 32 カラムまで指定できます。
`FLOAT`、`DOUBLE`、`NUMERIC`、`ARRAY`、`JSON`、`JSONB`、`DATE` などの複雑なデータの型のフィールドをプライマリキーとして設定することはできません。ただし、Hologres V1.3.22 以降では `DATE` 型のフィールドをプライマリキーとして使用することが可能です。`DATE` 型のフィールドをプライマリキーとして使用する場合は、ご利用の Hologres インスタンスのバージョンを確認し、必要に応じてインスタンスをスペックアップしてください。詳細については、「インスタンスの詳細」および「インスタンスのスペックアップ」をご参照ください。
行指向テーブルおよびハイブリッド行列表は、必ずプライマリキーを設定する必要があります。一方、列指向テーブルはプライマリキーの設定が必須ではありません。
プライマリキーは変更できません。プライマリキーを変更するには、テーブルを再作成する必要があります。
使用例
以下の例は、Hologres V2.1 以降の構文を示しています。ご利用のインスタンスが V2.0 以前のバージョンの場合、データ定義言語 (DDL) 内の `WITH (property = 'value')` 文を `CALL set_table_property` 文に置き換える必要があります。詳細については、「CREATE TABLE」をご参照ください。
標準的な列指向テーブルを作成し、プライマリキーを指定します。
V2.1 以降の構文:
CREATE TABLE tbl_1 ( id bigint NOT NULL, name text NOT NULL, age bigint NOT NULL, class text, reg_timestamp timestamptz NOT NULL, PRIMARY KEY (id) ) WITH ( orientation = 'column', distribution_key = 'id', clustering_key = 'age', event_time_column = 'reg_timestamp', bitmap_columns = 'name,class', dictionary_encoding_columns = 'class:auto' );すべてのバージョンで使用可能な構文:
BEGIN; CREATE TABLE tbl_1 ( id bigint NOT NULL, name text NOT NULL, age bigint, class text, reg_timestamp timesatmptz, PRIMARY KEY (id) ); CALL set_table_property('tbl_1', 'orientation', 'column'); CALL set_table_property('tbl_1', 'distribution_key', 'id'); CALL set_table_property('tbl_1', 'clustering_key', 'age'); CALL set_table_property('tbl_1', 'event_time_column', 'reg_timestamp'); CALL set_table_property('tbl_1', 'bitmap_columns', 'name,class'); CALL set_table_property('tbl_1', 'dictionary_encoding_columns', 'class:auto'); COMMIT;
標準的な列指向テーブルを作成し、2 つのカラムからなる複合プライマリキーを指定します。
V2.1 以降の構文:
CREATE TABLE tbl_1 ( id bigint NOT NULL, name text NOT NULL, age bigint NOT NULL, class text NOT NULL, reg_timestamp timestamptz NOT NULL, PRIMARY KEY (id,age) ) WITH ( orientation = 'column', distribution_key = 'id', clustering_key = 'age', event_time_column = 'reg_timestamp', bitmap_columns = 'name,class', dictionary_encoding_columns = 'class:auto' );すべてのバージョンで使用可能な構文:
BEGIN; CREATE TABLE tbl_2 ( id bigint NOT NULL, name text NOT NULL, age bigint NOT NULL, class text NOT NULL, reg_timestamp timestamptz NOT NULL, PRIMARY KEY (id,age) ); CALL set_table_property('tbl_2', 'orientation', 'column'); CALL set_table_property('tbl_2', 'distribution_key', 'id'); CALL set_table_property('tbl_2', 'clustering_key', 'age'); CALL set_table_property('tbl_2', 'event_time_column', 'reg_timestamp'); CALL set_table_property('tbl_2', 'bitmap_columns', 'name,class'); CALL set_table_property('tbl_2', 'dictionary_encoding_columns', 'class:auto'); COMMIT;
行指向テーブルを作成し、プライマリキーを指定します。
V2.1 以降の構文:
CREATE TABLE public.tbl_row ( id text NOT NULL, name text NOT NULL, class text, PRIMARY KEY (id) ) WITH ( orientation = 'row', distribution_key = 'id', clustering_key = 'id' );すべてのバージョンで使用可能な構文:
BEGIN; CREATE TABLE public.tbl_row ( id text NOT NULL, name text NOT NULL, class text , PRIMARY KEY (id) ); CALL set_table_property('public.tbl_row', 'orientation', 'row'); CALL set_table_property('public.tbl_row', 'clustering_key', 'id'); CALL set_table_property('public.tbl_row', 'distribution_key', 'id'); COMMIT;
パーティションテーブルを作成し、プライマリキーを指定します。
V2.1 以降の構文:
BEGIN; CREATE TABLE public.tbl_parent( a text , b int, c timestamp, d text, ds text, PRIMARY KEY (ds,b) ) PARTITION BY LIST(ds) WITH ( orientation = 'column'); CREATE TABLE public.tbl_child_1 PARTITION OF public.tbl_parent FOR VALUES IN('20221207'); CREATE TABLE public.tbl_child_2 PARTITION OF public.tbl_parent FOR VALUES IN('20221208'); COMMIT;すべてのバージョンで使用可能な構文:
BEGIN; CREATE TABLE public.tbl_parent( a text , b int, c timestamp, d text, ds text, PRIMARY KEY (ds,b) ) PARTITION BY LIST(ds); CALL set_table_property('public.tbl_parent', 'orientation', 'column'); CREATE TABLE public.tbl_child_1 PARTITION OF public.tbl_parent FOR VALUES IN('20221207'); CREATE TABLE public.tbl_child_2 PARTITION OF public.tbl_parent FOR VALUES IN('20221208'); COMMIT;
参考文献
クエリのユースケースに応じた適切なテーブルプロパティの設定方法については、「テーブル作成および最適化のユースケース別ガイド」をご参照ください。
キーバリュー (KV) クエリのユースケースにおけるテーブル作成およびクエリに関するベストプラクティスについては、「キーバリュークエリのユースケースにおけるベストプラクティス」をご参照ください。
Hologres の内部テーブル向け DDL ステートメントの詳細については、以下をご参照ください: