ソートキーとPrefix Index
Index Principles
Dorisは、SSTable(Sorted String table)に類似した構造でデータを保存します。この構造は、1つ以上の指定されたカラムに従ってソートして保存できる順序付きデータ構造です。このようなデータ構造では、ソート済みカラムの全部または一部に対する検索条件の検索は非常に効率的です。
Aggregate、Unique、およびDuplicateデータモデルでは、基盤となるデータストレージは、CREATE TABLE文でAGGREGATE KEY、UNIQUE KEY、およびDUPLICATE KEYの下で指定されたカラムに従ってそれぞれソートされます。これらのキーはソートキーと呼ばれます。ソートキーにより、Dorisはクエリ中にソート済みカラムに条件を指定することで、テーブル全体をスキャンすることなく必要なデータを素早く特定でき、検索の複雑さを軽減し、クエリを高速化できます。
ソートキーに基づいて、Dorisはプレフィックスインデックスを導入します。プレフィックスインデックスはスパースインデックスです。テーブル内のデータは、対応する行数に従って論理データブロック(Data Block)を形成します。各論理データブロックは、プレフィックスインデックステーブルにインデックスエントリを保存し、インデックスエントリの長さは36バイトを超えません。エントリの内容は、データブロック内の最初の行のソート済みカラムで構成されるプレフィックスです。プレフィックスインデックステーブルを検索する際、行データが配置されている論理データブロックの開始行番号を特定するのに役立ちます。プレフィックスインデックスは比較的小さいため、メモリに完全にキャッシュでき、データブロックの高速な特定が可能で、クエリ効率を大幅に向上させます。
データブロック内の行の最初の36バイトは、その行のプレフィックスインデックスとして使用されます。VARCHARタイプに遭遇した場合、プレフィックスインデックスは直接切り詰められます。最初のカラムがVARCHARの場合、36バイトに達していなくても直接切り詰められ、後続のカラムはプレフィックスインデックスに含まれません。
Use Cases
プレフィックスインデックスは、等価クエリと範囲クエリを高速化できます。
Managing Indexes
プレフィックスインデックスを定義する特別な構文はありません。テーブル作成時に、テーブルのKeyの最初の36バイトが自動的にプレフィックスインデックスとして使用されます。
プレフィックスインデックス選択の推奨事項
テーブルのKey定義は一意であるため、テーブルには1つのプレフィックスインデックスセットのみがあります。したがって、テーブル構造を設計する際に適切なプレフィックスインデックスを選択することが重要です。以下の推奨事項を考慮できます:
- WHERフィルタリング条件で最も一般的に使用されるフィールドをKeyとして選択する。
- より頻繁に使用されるフィールドを前に配置する。プレフィックスインデックスは、WHERE条件内でKeyのプレフィックスの一部であるフィールドに対してのみ有効です。
プレフィックスインデックスでカバーされていない他のカラムを条件として使用するクエリの場合、効率が要件を満たさない可能性があります。2つの解決策があります:
- 高速化が必要なクエリのカラムに転置インデックスを作成する。テーブルには多くの転置インデックスを持つことができます。
- DUPLICATEテーブルの場合、カラム順序を調整した対応する強整合性materialized viewsを作成することで、マルチプレフィックスインデックスを間接的に実現できます。詳細については、クエリ高速化/materialized viewsを参照してください。
Using Indexes
プレフィックスインデックスは、WHERE句での等価および範囲クエリを高速化するために使用されます。適用可能な場合は自動的に有効になり、特別な構文は必要ありません。
プレフィックスインデックスの高速化効果は、Query Profileの以下のメトリクスを使用して分析できます:
- RowsKeyRangeFiltered:プレフィックスインデックスによってフィルタリングされた行数。他のRows値と比較してインデックスのフィルタリング効果を分析できます。
Example Usage
- テーブルのソート済みカラムが以下のような場合、プレフィックスインデックスは:user_id(8 Bytes)+ age(4 Bytes)+ message(プレフィックス20 Bytes)となります。
| ColumnName | タイプ |
|---|---|
| user_id | BIGINT |
| age | INT |
| message | VARCHAR(100) |
| max_dwell_time | DATETIME |
| min_dwell_time | DATETIME |
- テーブルのソート済みカラムが以下のような場合、プレフィックスインデックスはuser_name(20 Bytes)となります。36バイトに達していなくても、VARCHARに遭遇したため直接切り詰められ、後続のカラムは含まれません。
| ColumnName | タイプ |
|---|---|
| user_name | VARCHAR(20) |
| age | INT |
| message | VARCHAR(100) |
| max_dwell_time | DATETIME |
| min_dwell_time | DATETIME |
- クエリ条件がプレフィックスインデックスのプレフィックスである場合、クエリを大幅に高速化できます。例えば、最初の例で以下のクエリを実行する場合:
SELECT * FROM table WHERE user_id = 1829239 AND age = 20;
このクエリは以下のクエリよりもはるかに効率的です:
SELECT * FROM table WHERE age = 20;
したがって、テーブル作成時に正しい列順序を選択することで、クエリ効率を大幅に向上させることができます。