Hologres はバージョン 4.0 以降でグローバルセカンダリインデックスをサポートしています。この機能により、プライマリキー以外の列に対する効率的なポイントクエリが可能になります。主キーインデックスとは異なり、セカンダリインデックスはデータの一意性を要求しませんが、特定の列に対するクエリパフォーマンスを大幅に向上させることができます。
前提条件
ご利用の Hologres インスタンスは、バージョン 4.0 以降である必要があります。インスタンスのバージョンが 4.0 より前の場合は、「インスタンスのアップグレード」をご参照ください。
制限事項
グローバルセカンダリインデックスの列は、`TEXT`、`INTEGER`、`BIGINT`、`VARCHAR` のデータ型のみをサポートします。
グローバルセカンダリインデックスは変更できません。
インデックスキー列と INCLUDE 列には、重複する列を含めることはできません。
ソーステーブルにはプライマリキーが必要です。
ソーステーブルに `time_to_live_in_seconds` パラメーターを設定することはできません。
グローバルセカンダリインデックスには、インデックスキー列と INCLUDE 列の両方を含め、最大 512 列まで設定できます。
グローバルセカンダリインデックスは、標準内部テーブルにのみ作成できます。物理パーティションテーブルまたは論理パーティションテーブルではサポートされていません。
ソーステーブルの列がグローバルセカンダリインデックスの一部である場合、その列を削除または変更することはできません。
グローバルセカンダリインデックスを持つソーステーブルに対して、Table Group の変更やリシャーディングを実行することはできません。
デフォルトでは、グローバルセカンダリインデックスは標準ストレージ (ホットストレージ) のみをサポートします。
グローバルセカンダリインデックスのストレージフォーマット (ローストア、列ストア、または行列ハイブリッドストア) は、そのソーステーブルのものと一致します。詳細は、以下のとおりです。
ソーステーブルがローストアを使用している場合、そのグローバルセカンダリインデックスもデフォルトでローストアを使用します。
ソーステーブルが列ストアを使用している場合、そのグローバルセカンダリインデックスもデフォルトで列ストアを使用します。
ソーステーブルが行列ハイブリッドストアを使用している場合、そのグローバルセカンダリインデックスもデフォルトで行列ハイブリッドストアを使用します。
グローバルセカンダリインデックスの作成
構文
CREATE GLOBAL INDEX [ IF NOT EXISTS ] index_name ON [schema_name.]table_name (index_column_name [, ...]) [ INCLUDE (include_column_name[, ...]) ]パラメーター
パラメーター
必須
説明
index_name
はい
グローバルセカンダリインデックスの名前。
schema_name
いいえ
ソーステーブルのスキーマ名。このパラメーターを指定しない場合、デフォルトのスキーマ名が使用されます。
table_name
はい
ソーステーブルの名前。
index_column_name
はい
グローバルセカンダリインデックスのインデックスキー列。プライマリキー以外の列に対するポイントクエリで使用されるフィルター列を設定することを推奨します。
include_column_name
いいえ
グローバルセカンダリインデックスに含める列。
使用上の注意
インデックスを作成するための SQL 文を送信すると、システムがその構築を開始します。
CREATE GLOBAL INDEX文は、インデックスが構築されて可視になるまで完了しません。インデックスの構築は、データの複数のコピーを書き込むため、書き込みパフォーマンスに影響します。書き込みパフォーマンスへの影響は、ソーステーブルのデータ量とインデックスの列数に応じて増加します。
グローバルセカンダリインデックスの作成時にスキーマを指定することはできません。インデックスはソーステーブルと同じスキーマに作成されます。
グローバルセカンダリインデックスを使用するには、クエリがインデックスによって完全にカバーされている必要があります。つまり、クエリ内のすべての列がインデックスキー列または INCLUDE 列である必要があります。
グローバルセカンダリインデックスの削除
構文
DROP INDEX [schema_name.]index_nameパラメーター
パラメーター名
必須
説明
schema_name
いいえ
グローバルセカンダリインデックスのスキーマ名。このパラメーターを指定しない場合、デフォルトのスキーマが使用されます。
index_name
はい
グローバルセカンダリインデックスの名前。
グローバルセカンダリインデックスの表示
現在のデータベース内のすべてのグローバルセカンダリインデックスを表示
SELECT n.nspname AS table_namespace, t.relname AS table_name, i.relname AS index_name FROM pg_class t JOIN pg_index ix ON t.oid = ix.indrelid JOIN pg_class i ON i.oid = ix.indexrelid JOIN pg_am am ON am.oid = i.relam JOIN pg_namespace n ON n.oid = t.relnamespace WHERE t.relkind = 'r' -- 標準テーブルのみをクエリ AND am.amname = 'globalindex'グローバルセカンダリインデックスが使用するストレージの表示
次のコードでは、
global_index_nameはグローバルセカンダリインデックスの名前を指定します。SELECT pg_relation_size('schema_name.global_index_name');グローバルセカンダリインデックスに含まれる列の表示
SELECT pg_catalog.pg_get_indexdef('global_index_name'::regclass, 0, true);
例
ある注文アプリケーションが、特定の注文優先度に基づいてデータを頻繁にクエリするとします。次の例では、orders テーブルを使用します。
フィールド名 | 型 | 意味 |
O_ORDERKEY | BIGINT | 注文番号 (プライマリキー)。 |
O_CUSTKEY | INT | 顧客 ID (CUSTOMER テーブルに関連付けられた外部キー)。 |
O_ORDERSTATUS | CHAR(1) | 注文ステータス ('F' = 完了、'O' = オープン、'P' = 処理中)。 |
O_TOTALPRICE | DECIMAL(15,2) | 注文合計金額。 |
O_ORDERDATE | DATE | 注文作成日。 |
O_ORDERPRIORITY | TEXT | 注文優先度 ('1-URGENT'、'2-HIGH' など)。 |
O_CLERK | TEXT | 注文を処理した担当者の従業員 ID。 |
O_SHIPPRIORITY | INT | 配送優先度 (値が大きいほど優先度が高い)。 |
O_COMMENT | TEXT | 注文コメント情報。 |
次の SQL 文は、例の orders テーブルを作成します。
CREATE TABLE ORDERS
(
O_ORDERKEY BIGINT NOT NULL PRIMARY KEY,
O_CUSTKEY INT NOT NULL,
O_ORDERSTATUS CHAR(1) NOT NULL,
O_TOTALPRICE DECIMAL(15,2) NOT NULL,
O_ORDERDATE DATE NOT NULL,
O_ORDERPRIORITY TEXT NOT NULL,
O_CLERK TEXT NOT NULL,
O_SHIPPRIORITY INT NOT NULL,
O_COMMENT TEXT NOT NULL
) WITH (
orientation='row,column',
segment_key='O_ORDERDATE',
distribution_key='O_ORDERKEY',
bitmap_columns='O_ORDERSTATUS,O_ORDERPRIORITY,O_CLERK,O_SHIPPRIORITY',
dictionary_encoding_columns='o_comment:off,o_orderpriority,o_clerk'
);
COMMENT ON TABLE ORDERS IS '基本的な注文情報とステータスを記録する主要な注文テーブル';
COMMENT ON COLUMN ORDERS.O_ORDERKEY IS '注文番号 (プライマリキー)';
COMMENT ON COLUMN ORDERS.O_CUSTKEY IS '顧客 ID (CUSTOMER テーブルに関連付けられた外部キー)';
COMMENT ON COLUMN ORDERS.O_ORDERSTATUS IS '注文ステータス (''F'' = 完了, ''O'' = オープン, ''P'' = 処理中)';
COMMENT ON COLUMN ORDERS.O_TOTALPRICE IS '注文合計金額';
COMMENT ON COLUMN ORDERS.O_ORDERDATE IS '注文作成日';
COMMENT ON COLUMN ORDERS.O_ORDERPRIORITY IS '注文優先度 (''1-URGENT'', ''2-HIGH'' など)';
COMMENT ON COLUMN ORDERS.O_CLERK IS '注文を処理した担当者の従業員 ID';
COMMENT ON COLUMN ORDERS.O_SHIPPRIORITY IS '配送優先度 (値が大きいほど優先度が高い)';
COMMENT ON COLUMN ORDERS.O_COMMENT IS '注文コメント情報';次の SQL 文は、特定の注文優先度を持つデータの高頻度クエリに使用されます:
SELECT O_ORDERKEY, O_CUSTKEY, O_ORDERSTATUS, O_TOTALPRICE, O_ORDERDATE, O_ORDERPRIORITY, O_CLERK, O_SHIPPRIORITY, O_COMMENT FROM ORDERS WHERE O_ORDERPRIORITY='1-URGENT'EXPLAINを使用すると、SQL 文の実行計画を確認できます:EXPLAIN SELECT O_ORDERKEY, O_CUSTKEY, O_ORDERSTATUS, O_TOTALPRICE, O_ORDERDATE, O_ORDERPRIORITY, O_CLERK, O_SHIPPRIORITY, O_COMMENT FROM ORDERS WHERE O_ORDERPRIORITY='1-URGENT'次の結果が返されます。
QUERY PLAN Gather (cost=0.00..1.00 rows=1 width=53) -> Local Gather (cost=0.00..1.00 rows=1 width=53) -> Index Scan using Clustering_index on orders (cost=0.00..1.00 rows=1 width=53) Bitmap Filter: (o_orderpriority = '1-URGENT'::text) Query Queue: init_warehouse.default_queue Optimizer: HQO version 4.0.0より効率的なクエリを実現するには、
O_ORDERPRIORITY列にインデックスを追加します。返された実行計画によると、クエリはビットマップインデックスを使用していますが、これによるパフォーマンスの向上は限定的です。より高いクエリ/秒 (QPS) を達成するには、
ordersテーブルのO_ORDERPRIORITYカラムにグローバルセカンダリインデックスを追加できます。CREATE GLOBAL INDEX idx_orders ON orders(O_ORDERPRIORITY) INCLUDE ( O_CUSTKEY, O_ORDERSTATUS, O_TOTALPRICE, O_ORDERDATE, O_CLERK, O_SHIPPRIORITY, O_COMMENT );インデックスを追加した後、再度
EXPLAIN文を実行して実行計画を確認します:QUERY PLAN Local Gather (cost=0.00..1.76 rows=3035601 width=99) -> Index Scan using Clustering_index on idx_orders (cost=0.00..1.54 rows=3035601 width=99) Shard Prune: Eagerly Shards selected: 1 out of 20 Cluster Filter: (o_orderpriority = '1-URGENT'::text) Query Queue: init_warehouse.default_queue Optimizer: HQO version 4.0.0現在の実行計画では、
Index Scan using Clustering_index onのオブジェクトがグローバルセカンダリインデックスidx_ordersであることが示されています。この計画では、シャードクリッピングも使用されます。この組み合わせにより、QPS を効果的に増やすことができます。Fixed Plan を使用して、QPS をさらに向上させることができます。
SET hg_experimental_enable_fixed_dispatcher_for_scan = true;実行計画を表示します。ポイントクエリが Fixed Plan を使用して最適化されていることがわかります。
