このトピックでは、Hologres でビットマップインデックスを使用する方法について説明します。
概要
Hologres では、bitmap_columns プロパティでビットマップインデックスを指定します。ビットマップインデックスは、データストレージとは独立したインデックス構造であり、等価クエリを高速化するように設計されています。ビットマップベクトルを使用してファイルブロック内のデータを迅速にフィルタリングするため、等価フィルタリングのシナリオに適しています。次の構文を使用します。
-- Hologres V2.1 以降でサポートされる構文
CREATE TABLE <table_name> (...) WITH (bitmap_columns = '[<columnName>{:[on|off]}[,...]]');
-- すべてのバージョンでサポートされる構文
CREATE TABLE <table_name> (...);
CALL set_table_property('<table_name>', 'bitmap_columns', '[<columnName>{:[on|off]}[,...]]');
|
パラメータ |
説明 |
|
table_name |
テーブルの名前。 |
|
columnName |
列の名前。 |
|
on |
指定した列のビットマップインデックスを有効にします。 |
|
off |
指定した列のビットマップインデックスを無効にします。 |
推奨事項
-
等価クエリで頻繁に使用される列にビットマップインデックスを作成することを推奨します。これにより、システムは一致するデータの行番号を迅速に特定できます。ただし、カーディナリティが高い列 (重複する値が少ない列) でビットマップインデックスを使用すると、大きなストレージオーバーヘッドが発生する可能性があります。
-
すべての列にビットマップインデックスを作成することは避けてください。そうすると、ストレージオーバーヘッドが増加するだけでなく、Hologres がデータインジェスト時に各列のインデックスを構築する必要があるため、書き込みスループットも低下します。
-
JSON 形式のデータを格納する
text列にはビットマップインデックスを作成しないでください。
制限事項
-
ビットマップインデックスは、列指向テーブルおよび行と列のハイブリッドテーブルではサポートされていますが、行指向テーブルではサポートされていません。
-
ビットマップインデックスが設定された列には NULL 値を含めることができます。
-
デフォルトでは、
textデータ型のすべての列にビットマップインデックスが暗黙的に作成されます。 -
トランザクションの外でコマンドを実行してビットマップインデックスを設定できます。Hologres はバックグラウンドでビットマップエンコーディングの作成と削除を非同期に実行するため、変更はすぐには有効になりません。詳細については、「ALTER TABLE」をご参照ください。
-
bitmap_columnsプロパティは、onまたはoffのみをサポートします。Hologres V2.0 以降、bitmap_columnsプロパティをautoに設定することはサポートされなくなりました。
仕組み
分散キーやクラスタリングキーとは異なり、ビットマップインデックスはデータストレージとは独立したインデックス構造です。クエリがこのインデックスを使用すると、行番号を迅速に特定してデータをフィルタリングできます。ただし、ビットマップインデックスにはオーバーヘッドがあります。次のシナリオを検討してください。
-
カーディナリティが高い列:Hologres は個別の値ごとにビットマップを生成します。重複しない値が多い場合、このプロセスはスパース配列を形成し、大量のストレージを消費します。
-
ワイドテーブルのすべての列にビットマップインデックスがある場合:Hologres はデータインジェスト時に各値のビットマップを構築する必要があるため、システムオーバーヘッドが発生し、書き込みスループットが低下します。
要約すると、ビットマップインデックスは空間と時間のトレードオフです。データ分布が比較的均等な列で最もコスト効率が高くなります。
次の例に示すように、explain SQL を使用して、クエリがビットマップインデックスを使用しているかどうかを確認できます。実行計画に Bitmap Filter が含まれている場合、クエリはインデックスを使用しています。
-
Hologres V2.1 以降でサポートされる構文:
CREATE TABLE bitmap_test ( uid int NOT NULL, name text NOT NULL, gender text NOT NULL, class text NOT NULL, PRIMARY KEY (uid) ) WITH ( bitmap_columns = 'gender,class' ); INSERT INTO bitmap_test VALUES (1,'田中','Male','Class 1'), (2,'鈴木','Male','Class 3'), (3,'佐藤','Female','Class 2'), (4,'伊藤','Female','Class 2'), (5,'渡辺','Male','Class 2'), (6,'山本','Male','Class 3'), (7,'中村','Female','Class 1'); explain SELECT * FROM bitmap_test where gender='Male' AND class='Class 1'; -
すべてのバージョンでサポートされる構文:
begin; create table bitmap_test ( uid int not null, name text not null, gender text not null, class text not null, PRIMARY KEY (uid) ); call set_table_property('bitmap_test', 'bitmap_columns', 'gender,class'); commit; INSERT INTO bitmap_test VALUES (1,'田中','Male','Class 1'), (2,'鈴木','Male','Class 3'), (3,'佐藤','Female','Class 2'), (4,'伊藤','Female','Class 2'), (5,'渡辺','Male','Class 2'), (6,'山本','Male','Class 3'), (7,'中村','Female','Class 1'); explain SELECT * FROM bitmap_test where gender='Male' AND class='Class 1';
実行計画に Bitmap Filter オペレーター (例:Bitmap Filter: (gender = 'Male'::text) AND (class = 'Class 1'::text)) が含まれていることから、クエリがビットマップインデックスを使用したことが確認できます。
ビットマップインデックスとクラスタリングキーの比較
-
ビットマップインデックスとクラスタリングキーは、どちらもファイル内のデータをフィルタリングします。
-
ビットマップインデックスは、行番号でデータを特定するため、等価クエリに適しています。一方、クラスタリングキーはファイル内のデータをソートするため、範囲クエリに適しています。
クラスタリングキーはビットマップインデックスよりも優先されます。同じ列に両方が作成されている場合、オプティマイザはクラスタリングキーを優先的に使用します。次の例で詳細を示します。
-
Hologres V2.1 以降でサポートされる構文:
-- uid、class、date 列がクラスタリングキーとして設定されています。 -- デフォルトでは、name、class、date などの text 列にはビットマップインデックスがあります。 CREATE TABLE ck_bit_test ( uid int NOT NULL, name text NOT NULL, class text NOT NULL, date text NOT NULL, PRIMARY KEY (uid) ) WITH ( clustering_key = 'uid,class,date', bitmap_columns = 'name,class,date' ); INSERT INTO ck_bit_test VALUES (1,'田中','1','2022-10-19'), (2,'鈴木','3','2022-10-19'), (3,'佐藤','2','2022-10-20'), (4,'伊藤','2','2022-10-20'), (5,'渡辺','2','2022-10-18'), (6,'山本','3','2022-10-17'), (7,'中村','3','2022-10-20'); -
すべてのバージョンでサポートされる構文:
-- uid、class、date 列がクラスタリングキーとして設定されています。 -- デフォルトでは、name、class、date などの text 列にはビットマップインデックスがあります。 begin; create table ck_bit_test ( uid int not null, name text not null, class text not null, date text not null, PRIMARY KEY (uid) ); call set_table_property('ck_bit_test', 'clustering_key', 'uid,class,date'); call set_table_property('ck_bit_test', 'bitmap_columns', 'name,class,date'); commit; INSERT INTO ck_bit_test VALUES (1,'田中','1','2022-10-19'), (2,'鈴木','3','2022-10-19'), (3,'佐藤','2','2022-10-20'), (4,'伊藤','2','2022-10-20'), (5,'渡辺','2','2022-10-18'), (6,'山本','3','2022-10-17'), (7,'中村','3','2022-10-20');
-
この等価クエリは
uid,class,date列を対象としています。最左一致の原則に従っているため、オプティマイザはビットマップインデックスではなくクラスタリングキーを使用します。SELECT * FROM ck_bit_test WHERE uid = '3' AND class ='2' AND date > '2022-10-17';実行計画には
Cluster Filterオペレーターが含まれていますが、Bitmap Filterオペレーターは含まれていません。これは、クエリがクラスタリングキーを使用したことを示しています。計画にはIndex Scan using holo_index:[1] on ck_bit_testが示され、Cluster Filter: ((uid = 3) AND (class = '2'::text) AND (date > '2022-10-17'::text))を使用してフィルタリングしており、クラスタリングキーの使用が確認できます。 -
クエリは
uid,class,date列に対して実行されます。ただし、class列は範囲クエリで使用されています。最左一致の原則によれば、>または<が SQL クエリで使用されると一致が停止します。したがって、date列の述語はクラスタリングキーを使用できません。date列にビットマップインデックスが存在するため、クエリは代わりにそれを使用します。SELECT * FROM ck_bit_test WHERE uid = '3' AND class >'2' AND date = '2022-10-17';実行計画には
Cluster FilterオペレーターとBitmap Filterオペレーターの両方が含まれています。これは、クエリがuid,class列にはクラスタリングキーを使用し、date列にはビットマップインデックスを使用したことを示しています。explain SELECT * FROM ck_bit_test WHERE uid = '3' AND class >'2' AND date = '2022-10-17'; QUERY PLAN Exchange (Gather Exchange) (cost=0.00..1.10 rows=1 width=24) -> Decode (cost=0.00..1.10 rows=1 width=24) -> Index Scan using holo_index:[1] on ck_bit_test (cost=0.00..1.00 rows=1 width=24) Cluster Filter: ((uid = 3) AND (class > '2'::text)) Bitmap Filter: (date = '2022-10-17'::text) Shard Selector(Eagerly): ->: l0 [3] Optimizer: HQO version 1.3.0
-
例
-
Hologres V2.1 以降でサポートされる構文:
CREATE TABLE tbl ( a text NOT NULL, b text NOT NULL ) WITH ( bitmap_columns = 'a:on,b:off' ); -- bitmap_columns を変更 ALTER TABLE tbl SET (bitmap_columns = 'a:off');-- ALTER TABLE ステートメントは完全な変更のみをサポートします。 -
すべてのバージョンでサポートされる構文:
-- tbl テーブルを作成し、ビットマップインデックスを設定します。 begin; create table tbl ( a text not null, b text not null ); call set_table_property('tbl', 'bitmap_columns', 'a:on,b:off'); commit; -- ビットマップインデックスを変更します。 call set_table_property('tbl', 'bitmap_columns', 'a:off');-- 完全な変更。列 a のビットマップインデックスを無効にします。
関連ドキュメント
次のトピックでは、Hologres の内部テーブルに関するデータ定義言語 (DDL) ステートメントの詳細情報を提供しています。