大規模なデータセットに対して、プライマリキー に基づく UPDATE 操作や 範囲フィルター 条件を含むクエリを頻繁に実行する場合、イベント時間列 (セグメントキー) の設定を検討してください。システムは、ファイルをマージする前に イベント時間列 の範囲に基づいてデータファイルを並べ替えます。このプロセスにより、ファイル間の重複が減少し、クエリエンジンが可能な限り多くのファイルをプルーニングできるようになり、クエリ効率が向上します。適切に設定された イベント時間列 は、クエリ速度と全体的なパフォーマンスを向上させます。このトピックでは、Hologres のテーブルに event_time_column プロパティを設定する方法を説明します。
イベント時間列
event_time_column プロパティは、以前は セグメントキー という名前でした。Hologres V0.9 以降では、デフォルトのプロパティ名は event_time_column です。セグメントキー プロパティは、下位互換性のために保持されています。
イベント時間列 は、主に次のシナリオで使用されます。
-
範囲フィルターまたは等値条件を含むクエリ。 -
プライマリキーに基づくUPDATE操作。
event_time_column プロパティは、テーブルの作成時に指定する必要があります。次の構文を使用します。
-- Hologres V2.1 以降でサポートされている構文
CREATE TABLE <table_name> (...) WITH (event_time_column = '[<columnName>[,...]]');
-- すべてのバージョンでサポートされている構文
BEGIN;
CREATE TABLE <table_name> (...);
call set_table_property('<table_name>', 'event_time_column', '[<columnName>[,...]]');
COMMIT;
パラメーター:
|
パラメーター |
説明 |
|
table_name |
テーブルの名前。 |
|
columnName |
|
推奨事項
-
イベント時間列は、タイムスタンプ列など、単調に増加または減少する値を持つ列に最適です。ログやトラフィックデータなどの時間関連データに理想的であり、適切な設定によってパフォーマンスを大幅に向上させることができます。イベント時間列が完全に順不同である場合、マージされたファイルは明確な値の範囲を持たず、ファイルプルーニングの利点が失われます。 -
テーブルに明確な単調増加または単調減少の列がない場合は、
update_timeなどの列を追加し、各アップサート操作で現在の時刻を書き込むことを検討してください。 -
イベント時間列は最左一致の原則に従います。複数の列を設定すると、高速化の対象となるクエリパターンが制限される可能性があります。したがって、ほとんどの場合、2列以下を指定することを推奨します。
制限事項
-
イベント時間列は、NOT NULLとして定義されている列または列の組み合わせである必要があります。event_time_columnプロパティを省略することはできますが、NULL 値を許可する列に設定することはできません。Hologres V1.3.20 から V1.3.27 までは、event_time_columnプロパティに NULL 値を許容する列の指定がサポートされていました。Hologres V1.3.28 以降、NULL 値を許容するイベント時間列はデータ整合性を損なう可能性があるため、この機能はサポートされなくなりました。ビジネス要件上、NULL 値を許容する列をイベント時間列として設定する必要がある場合は、SQL ステートメントの前に次のステートメントを追加できます。set hg_experimental_enable_nullable_segment_key = true;次の SQL ステートメントを使用して、現在のデータベースに NULL 値を許容する
イベント時間列(またはセグメントキー) が含まれているか確認できます。WITH t_base AS ( SELECT * FROM hologres.hg_table_info WHERE collect_time::date = CURRENT_DATE ), t1 AS ( SELECT db_name, schema_name, table_name, jsonb_array_elements(table_meta::jsonb -> 'columns') cols FROM t_base ), t2 AS ( SELECT db_name, schema_name, table_name, cols ->> 'name' col_name FROM t1 WHERE cols -> 'nullable' = 'true'::jsonb ), t3 AS ( SELECT db_name, schema_name, table_name, regexp_replace(regexp_split_to_table(table_meta::jsonb ->> 'segment_key', ','), ':asc|:desc$', '') segment_key_col FROM t_base WHERE table_meta::jsonb -> 'segment_key' IS NOT NULL ) SELECT CURRENT_DATE, t3.db_name, t3.schema_name, t3.table_name, jsonb_build_object('nullable_segment_key_column', string_agg(t3.segment_key_col, ',')) as nullable_segment_key_column FROM t2, t3 WHERE t3.db_name = t2.db_name AND t3.schema_name = t2.schema_name AND t3.table_name = t2.table_name AND t2.col_name = t3.segment_key_col GROUP BY t3.db_name, t3.schema_name, t3.table_name; -
テーブルの作成後に
event_time_columnプロパティを変更することはできません。変更するには、テーブルを再作成する必要があります。 -
行指向テーブルにイベント時間列を設定することはできません。 -
列指向テーブルの場合、イベント時間列を明示的に設定しないと、Hologres はデフォルトで、TIMESTAMPまたはTIMESTAMPTZデータ型の最初のNOT NULL列をイベント時間列として使用します。そのような列が存在しない場合は、DATEデータ型の最初のNOT NULL列が使用されます。Hologres V0.9 より前のバージョンでは、デフォルトのイベント時間列は設定されません。 -
DECIMAL、NUMERIC、FLOAT、DOUBLE、ARRAY、JSON、JSONB、BIT、MONEY、またはその他の複雑なデータ型をイベント時間列として使用することはできません。
仕組み
次の図は、単一の シャード 内でのデータ書き込みプロセスを示しています。
-
シャード内では、書き込みパフォーマンスを最大化するために、データはまず追記専用モードでインメモリテーブルに書き込まれます。インメモリテーブルのサイズは固定です。インメモリテーブルがいっぱいになると、システムはそのデータを非同期でファイルにフラッシュします。 -
書き込みパフォーマンスを最適化するために、データは追記専用モードで書き込まれ、時間の経過とともにファイル数が増加します。システムはバックグラウンドでこれらのファイルを定期的にマージします。
イベント時間列(またはセグメントキー) を設定すると、システムはイベント時間列の範囲に基づいてファイルを並べ替え、隣接する範囲のファイルをマージします。このプロセスにより、ファイル間の重複が減少し、クエリオプティマイザーがより多くのファイルをプルーニングできるようになり、クエリ効率が向上します。 -
ファイルは
イベント時間列に基づいてソートされます。したがって、イベント時間列も最左一致の原則に従います。たとえば、列a、b、cをイベント時間列として設定した場合、フィルター条件がa,b,cまたはa,bの場合、クエリはこの設定の恩恵を受けられます。フィルター条件がa,cの場合、列aのみが恩恵を受けます。フィルター条件がb,cの場合、クエリはイベント時間列の恩恵を受けられません。
前述のように、イベント時間列 は次のシナリオを高速化できます。
-
範囲フィルターまたは等値条件を含むクエリ。クエリ対象の列が
イベント時間列として設定されている場合、Hologres はクエリ内の範囲条件を列のファイルレベルの統計情報 (min/max) と比較します。これにより、Hologres は無関係なファイルを迅速にプルーニングし、クエリを高速化できます。 -
プライマリキーに基づくUPDATE操作。Hologres の
UPDATEコマンドは、DELETEコマンドとINSERTコマンドの組み合わせとして実装されています。プライマリキーベースの UPDATE または INSERT ON CONFLICT (アップサート) を伴うシナリオでは、まずプライマリキーを使用してターゲットテーブル内の古いデータのセグメントキーを見つけます。次に、このセグメントキーを使用して古いデータを含むファイルを特定し、最終的にデータをDELETEとしてマークします。セグメントキーが適切に設定されていれば、古いデータを含むファイルを迅速に特定でき、書き込みパフォーマンスが向上します。逆に、列指向テーブルにセグメントキーが設定されていない場合、セグメントキーが不適切なフィールドで設定されている場合、またはデータ書き込み時にセグメントキーのフィールドが時間と強い相関関係を持たない場合 (たとえば、データがほとんど順不同である場合) は、古いデータを見つけるために多数のファイルをスキャンする必要があります。このプロセスは、多数の I/O 操作を引き起こすだけでなく、大量の CPU リソースを消費し、書き込みパフォーマンスとインスタンス全体の負荷に悪影響を及ぼします。
例
-
テーブル作成時に単一の
イベント時間列を作成する。-
Hologres V2.1 以降でサポートされている構文:
CREATE TABLE tbl_segment_test ( a int NOT NULL, b timestamptz NOT NULL ) WITH ( event_time_column = 'b' ); INSERT INTO tbl_segment_test values (1,'2022-09-05 10:23:54+08'), (2,'2022-09-05 10:24:54+08'), (3,'2022-09-05 10:25:54+08'), (4,'2022-09-05 10:26:54+08'); EXPLAIN SELECT * FROM tbl_segment_test WHERE b > '2022-09-05 10:24:54+08'; -
すべてのバージョンでサポートされている構文:
BEGIN; CREATE TABLE tbl_segment_test ( a int NOT NULL, b timestamptz NOT NULL ); CALL set_table_property('tbl_segment_test', 'event_time_column', 'b'); COMMIT; INSERT INTO tbl_segment_test VALUES (1,'2022-09-05 10:23:54+08'), (2,'2022-09-05 10:24:54+08'), (3,'2022-09-05 10:25:54+08'), (4,'2022-09-05 10:26:54+08'); EXPLAIN SELECT * FROM tbl_segment_test WHERE b > '2022-09-05 10:24:54+08';
EXPLAINステートメントを実行すると、実行計画を確認できます。計画にSegment Filterが表示される場合、クエリはイベント時間列を使用しています。次の計画にはSegment Filterが含まれており、イベント時間列が有効であることを示しています。QUERY PLAN Gather (cost=0.00..1.10 rows=1 width=12) -> Exchange (Gather Exchange) (cost=0.00..1.10 rows=1 width=12) -> Decode (cost=0.00..1.10 rows=1 width=12) -> Index Scan using holo_index:[1] on tbl_segment_test (cost=0.00..1.00 rows=1 width=12) Segment Filter: (b > '2022-09-05 10:24:54+08'::timestamp with time zone) Optimizer: HQO version 1.3.0 -
-
テーブル作成時に複数の
イベント時間列を作成する。-
Hologres V2.1 以降でサポートされている構文:
CREATE TABLE tbl_segment_test_2 ( a int NOT NULL, b timestamptz NOT NULL ) WITH ( event_time_column = 'a,b' ); INSERT INTO tbl_segment_test_2 VALUES (1,'2022-09-05 10:23:54+08'), (2,'2022-09-05 10:24:54+08'), (3,'2022-09-05 10:25:54+08'), (4,'2022-09-05 10:26:54+08') ; -- クエリはイベント時間列を使用しません。 SELECT * FROM tbl_segment_test_2 WHERE b > '2022-09-05 10:24:54+08'; -- クエリはイベント時間列を使用します。 SELECT * FROM tbl_segment_test_2 WHERE a = 3 and b > '2022-09-05 10:24:54+08'; SELECT * FROM tbl_segment_test_2 WHERE a > 3 and b < '2022-09-05 10:26:54+08'; SELECT * FROM tbl_segment_test_2 WHERE a > 3 and b > '2022-09-05 10:24:54+08'; -
すべてのバージョンでサポートされている構文:
BEGIN; CREATE TABLE tbl_segment_test_2 ( a int NOT NULL, b timestamptz NOT NULL ); CALL set_table_property('tbl_segment_test_2', 'event_time_column', 'a,b'); COMMIT; INSERT INTO tbl_segment_test_2 VALUES (1,'2022-09-05 10:23:54+08'), (2,'2022-09-05 10:24:54+08'), (3,'2022-09-05 10:25:54+08'), (4,'2022-09-05 10:26:54+08') ; -- クエリはイベント時間列を使用しません。 SELECT * FROM tbl_segment_test_2 WHERE b > '2022-09-05 10:24:54+08'; -- クエリはイベント時間列を使用します。 SELECT * FROM tbl_segment_test_2 WHERE a = 3 and b > '2022-09-05 10:24:54+08'; SELECT * FROM tbl_segment_test_2 WHERE a > 3 and b < '2022-09-05 10:26:54+08'; SELECT * FROM tbl_segment_test_2 WHERE a > 3 and b > '2022-09-05 10:24:54+08';
-
関連トピック
-
クエリパターンに適したテーブルプロパティの選択に関するガイダンスは、「シナリオ別のテーブル作成とチューニングガイド」をご参照ください。
-
Hologres 内部テーブルに関連する DDL ステートメントについては、以下をご参照ください。