OceanBaseデータベースは、さまざまなアルゴリズムに基づくベクトルインデックスを提供しており、ユーザーは使用シナリオに応じて適切なインデックスタイプを選択できます。
注意
本記事の実践内容は、V4.3.5 BP3以降のバージョンにのみ適用されます。
HNSWかIVF?
OceanBaseの密インデックスは大きく2つのカテゴリに分類されます:
- グラフベースの HNSW シリーズインデックス:HNSW、HNSW_SQ、HNSW_BQ。
- ディスクベースの IVF シリーズインデックス:IVF、IVF_PQ。
この2つのインデックスタイプはそれぞれ特徴を持ちます。HNSW シリーズは通常、高いクエリ性能を提供しますが、より多くのメモリを消費します。一方、IVF シリーズはキャッシュが十分な場合に良好な性能を発揮し、メモリに依存することなく動作できます。しかし、HNSW と IVF の選択はメモリの考慮だけではありません。ビジネスシナリオ、データ規模、パフォーマンス指標、リソース制約など、さまざまな側面を総合的に評価する必要があります。以下では、その核心的な違いを詳細に比較し、選択のアドバイスを提供します。
核心差异对比
| 比較項目 | HNSW シリーズ | IVF シリーズ |
|---|---|---|
| ストレージ方式 | メモリベースのグラフ構造インデックス | ディスクベースのインデックス |
| メモリ使用量 | 完全にメモリにロードする必要があり、メモリ使用量が高い | メモリに依存せず、メモリ使用量が低い |
| クエリ性能(QPS) | 非常に高い、ミリ秒級のレスポンス | 高い、キャッシュが十分な場合、HNSWに近づく |
| 叫率 | 高い、99%に達する | 高い、HNSWにやや劣るが、パラメータのチューニングで改善可能 |
| ビルド速度 | 慢い、グラフ構造を構築する必要がある | 高速、クラスタリングアルゴリズムに基づく |
| 適用データ量 | 百万件から億件 | 百万件から十億件 |
| コスト | メモリコストが高め | ストレージコストが低く、大規模データに適している |
| 実時性 | 実時DML操作をサポート | 実時DML操作をサポート |
决策流程图
説明
- インデックスタイプを選択する前に、ベクトルインデックスのメモリ管理を参照してメモリ使用量を推定する必要があります。
- 決定フローチャートの選択アドバイスはすべて1024次元のベクトルを基準としています。実際の次元が異なる場合は、比率に応じて必要なリソースを近似的に換算できます。
- 決定フローチャートは主にメモリコストの観点から、インデックスタイプの選択を助けるために作成されています。
- テナントのメモリが十分であっても、必ずしもHNSWなどの最高グレードのインデックスを選択する必要はありません。極限のパフォーマンスを求める場合は、HNSW_SQなどのコストパフォーマンスの高いオプションを検討することもできます。
注意
ここでは一部の一般的なシナリオの決定フローチャートを例として挙げています。上記のパスで判断できない場合や、他の要件がある場合は、OceanBase技術サポートにお問い合わせください。
パーティションテーブルを使用しますか?
パーティションテーブルを使用する主な目的は、大規模データのシナリオを解決することです。次に、クエリ条件がパーティションキーとして使用できる場合、パーティションプルーニングによりクエリパフォーマンスを向上させることができます。以下の2つのシナリオではパーティションテーブルを使用することを推奨します:
- データ量が数千万件または1億件を超える場合:データ量が非常に大きい場合、パーティションテーブルを使用することでデータを複数のパーティションに分散させ、各パーティションで独立してインデックスを構築できるため、単一クエリの負荷を軽減し、全体的なクエリパフォーマンスを向上させることができます。
- クエリ条件に明確なスカラーカラムがあり、パーティションプルーニングに使用できる場合:例えば、
labelフィールドが常にWHERE条件に含まれる場合、パーティションキーとしてlabelを使用してパーティションテーブルを作成し、パーティションプルーニングによってクエリ対象のパーティション数を削減することができます。
具体的な使用推奨事項は以下のとおりです:
パーティションの分割
ベクトルインデックスを使用する際は、パーティション数を多すぎないようにすることが望ましいです。スカラーアイテムと異なり、ベクトルインデックス(例:HNSW)では、同じ設定下でインデックスの規模が100万ベクトルから200万ベクトルへ増加しても、クエリTopKに必要な計算コストは大幅に増加しません。そのため、パーティションスキャンの最適化が利用できない場合、パーティション数を多めにすることは性能を低下させる可能性があります。また、単一のパーティションが非常に大きいと、インデックス再構築にかかる時間が増え、スカラーコンディションとの結合クエリ時の効率にも悪影響を及ぼします。
以上より、各パーティション内のデータ量は2000万以下に抑え、パーティションプルーニングをサポートするフィールドをパーティションキーとして選択することを推奨します。
アルゴリズムの選択
大規模なデータ量の場合は、HNSW_BQまたはIVF_PQインデックスを推奨します。他のインデックスを使用する場合は、以下のメモリ使用量セクションを参照して推定してください。
メモリ使用量
HNSW_BQ
HNSW_BQインデックスの場合、テナントメモリ > HNSW_BQクエリ時の総メモリ使用量 + 単一パーティションのHNSW_SQインデックスの使用量を推奨します。メモリの推定プロセスは以下のとおりです。
INDEX_VECTOR_MEMORY_ADVISOR関数を使用して、HNSW_BQおよびHNSW_SQインデックスの構築とクエリプロセスにおける推奨メモリ値を優先的に計算します。- 上記のツールから得られた推奨メモリ値に基づいて、テナントが必要とする総メモリ量を計算し決定します。
例えば、1億件の1024次元ベクトルデータを10パーティションに分割(各パーティション約1000万件)して使用する場合、上記のプロセスに従って具体的な計算は以下のとおりです。
-- REFINE_TYPE=SQ8を指定することで、HNSW_BQインデックスの構築およびクエリプロセスにおける推奨メモリ値を直接かつ正確に取得できます。
-- HNSW_SQインデックスの使用量を別途計算する必要はありません。これは、HNSW_BQインデックスの構築時にデフォルトでSQ8量子化アルゴリズムを使用するためです。
-- refine_type=sq8を指定すると、関数はこのインデックス構築時に必要なSQ8量子化ベクトルのメモリ使用量を自動的に計算します。
-- HNSW_BQインデックスの推奨メモリ値は74.6GBで、クエリ時のメモリ使用量は57.4GBです。ここでは推奨メモリ値を使用します。
SELECT DBMS_VECTOR.INDEX_VECTOR_MEMORY_ADVISOR('HNSW_BQ',100000000,1024,'FLOAT32','M=32,DISTANCE=COSINE,REFINE_TYPE=SQ8', 10000000);
+------------------------------------------------------------------------------------------------------------------------------+
| DBMS_VECTOR.INDEX_VECTOR_MEMORY_ADVISOR('HNSW_BQ',100000000,1024,'FLOAT32','M=32,DISTANCE=COSINE,REFINE_TYPE=SQ8', 10000000) |
+------------------------------------------------------------------------------------------------------------------------------+
| Suggested minimum vector memory is 74.6 GB, memory consumption when providing search service is 57.4 GB |
+------------------------------------------------------------------------------------------------------------------------------+
1 row in set
-- ベクトルメモリはテナントメモリのデフォルトで50%を占めるため、総テナントメモリは
SELECT 74.6/0.5;
+--------------------------------------------------------------------------------------------------------------+
| 74.6/0.5 = 149.2 GB |
+--------------------------------------------------------------------------------------------------------------+
1 row in set
-- 実際の環境では新規に書き込まれたデータが圧縮されていない場合があるため、余裕をもって設定することを推奨します。
SELECT 149.2 * 1.2;
+--------------------------------------------------------------------------------------------------------------+
| 149.2 * 1.2 = 179.04 GB |
+--------------------------------------------------------------------------------------------------------------+
1 row in set
-- そのため、テナントメモリを179GBに設定することを推奨します。
IVF シリーズ
IVF および IVF_PQ インデックスの場合、テナントメモリ > 単一パーティション構築メモリ + 全パーティション常駐メモリの合計が推奨されます。例えば、1億件のデータを10個のパーティションに分割し、各パーティションに約1000万のベクトルを配置した場合、単一パーティションの構築には約2.7GBのメモリが必要となり、クエリ時のIVF_PQインデックスの合計常駐メモリは約1.1GB(110MB/パーティション)となります。そのため、最低でも約3GBのメモリを確保する必要があります。余裕をもって配置するため、6GBのメモリを推奨します。他のデータ量のシナリオでも同様の方法で推定できます。
ビルドとクエリパラメータ
インデックスのビルドとクエリパラメータは、単一パーティションの最大データ量を基準として設定することを推奨します。詳細については、以下のインデックスパラメータの推奨事項セクションを参照してください。
性能とリコール率
- クエリ条件が単一のパーティションに制限できる場合:性能とリコール率は単一パーティションのシナリオと同様です。詳細については、以下のデータ量の規模ごとの詳細な説明のセクションを参照してください。
- クエリ条件が単一のパーティションに制限できない場合:QPSは単一のOBServerノード上のパーティション数に比例して予測できます(例:単一ノードに3つのパーティションがある場合、QPSは単一パーティションの性能の約1/3となります)。また、パーティション間のクエリではより多くの候補結果がマージされるため、実際のリコール率は通常単一パーティションのシナリオよりも高くなります。
インデックスパラメータの推奨事項
HNSW シリーズ
同シリーズのインデックスは、データ量が異なる場合、推奨されるインデックス構築とクエリパラメータが異なります。本記事では、百万件と千万件のデータ量、768次元のベクトルデータに対するHNSW/HNSW_SQ/HNSW_BQインデックスの推奨設定を示します。億件規模のベクトルデータについては、本記事の後述の章で説明するIVF_PQインデックス、またはパーティションテーブル内のHNSW_BQインデックスを選択してください。
注意
データ量が増加する見込みの場合は、最終的なデータ量に基づいてパラメータを設定することを推奨します。
注意
HNSW_BQは高圧縮率の量子化アルゴリズムであり、低次元ベクトルのリコール率の上限が低い場合があります。パフォーマンスの損失を避けるため、HNSW_BQは512次元以上のベクトルに使用することを推奨します。
| シナリオ | インデックスタイプ | パラメータの推奨 |
|---|---|---|
| 最大リコール (メモリ使用量が最大) |
HNSW | 100万件のデータ量:m = 16、ef_construction = 200、ef_search = 100、その他のパラメータはデフォルト値 |
| 最高パフォーマンス (メモリ使用量が少ない) |
HNSW_SQ | 100万件のデータ量:m = 16、ef_construction = 200、ef_search = 100、その他のパラメータはデフォルト値 1000万件のデータ量:m = 32、ef_construction = 400、ef_search = 350、その他のパラメータはデフォルト値 |
| 最もコストパフォーマンスが良い (メモリ使用量が少なく、パフォーマンスが良い) |
HNSW_BQ | 100万件のデータ量:m = 16、ef_construction = 200、ef_search = 100、その他のパラメータはデフォルト値 1000万件のデータ量:m = 32、ef_construction = 400、ef_search = 1000、refine_k = 10、その他のパラメータはデフォルト値 1億件のデータ量:パーティションテーブルを使用し、m = 32、ef_construction = 400、ef_search = 1000、refine_k = 10、その他のパラメータはデフォルト値 |
100万件のデータ量の詳細
100万件の768次元ベクトルデータを例に(上記の表の構築パラメータを使用)、メモリ使用量とリコール率のチューニングを補足説明します。
メモリ使用量:
| インデックスタイプ | 推奨テナントメモリ | 説明 |
|---|---|---|
| HNSW | 15 GB | ベクトルインデックスのメモリサイズの推奨値は7.3 GBです。テナントメモリが8 GBを超える場合、ベクトルインデックスはデフォルトでテナントメモリの最大50%まで使用します。テナントメモリが8 GB以下の場合、ベクトルインデックスはデフォルトでテナントメモリの最大40%まで使用します。したがって、テナントメモリは約15 GB必要です。 |
| HNSW_SQ | 6 GB | ベクトルインデックスのメモリサイズの推奨値は2.1 GBです。 |
| HNSW_BQ | 6 GB | HNSW_BQインデックスは構築時に高精度のベクトルが必要なので、構築過程でのメモリ要件はHNSW_SQと同じ6 GBです。HNSW_BQインデックスはデフォルトでSQ8量子化メソッドを使用し、インデックス構築完了後、メモリ使用量は大幅に低下し、約405 MBになります。 上記の説明はパーティションテーブルのないシナリオに適用されます。パーティションテーブルを使用する場合、OceanBaseはテナントに割り当てられたメモリに基づいて、同時に構築できるパーティション数を動的に調整します。実際の設定では、テナントメモリにHNSW_BQのクエリ時のメモリ使用量に加えて、あるパーティションを構築する際のHNSW_SQのメモリ要件を含め、一定の余裕を確保することを推奨します。具体的な計算方法については、上記の メモリ使用量 章節を参照してください。 |
リコール率のチューニング:
ef_search と refine_k(HNSW_BQのみ)パラメータを調整することで、より多くのベクトル計算によりリコール率を向上させることができます。ただし、これに伴いクエリ性能が低下する可能性があります。異なるTopN値の場合、以下の表の推奨値を設定できます。リコール率をさらに向上させる必要がある場合は、パラメータ値をより大きく設定することができます。
注意
リコール率はデータの特性と直接的な関係があります。以下の表は、768次元の標準データセットにおいて、リコール率が0.95程度になる推奨値です。
| TopN | ef_search | refine_k(HNSW_BQのみ) |
|---|---|---|
| Top10 | 64 | 4 |
| Top100 | 240 | 4 |
極限リコール率の説明:
いくつかのインデックスアルゴリズムの極限リコール率は異なります。本節で推奨される構築パラメータを設定した場合、ef_search を1000に設定すると、クエリのリコール率は向上する可能性がありますが、QPSは0.95のリコール率時の約1/3まで低下します。また、ef_search を大きくしても、すべてのタイプのインデックスのリコール率が無限に向上するわけではありません。HNSWのみが0.99以上のリコール率に達することができます。HNSW_BQインデックスは、refine_k をさらに増加させることでリコール率を向上させることができます。ただし、これに伴い性能もさらに低下します。
極限リコール率の参考値(ef_search = 1000):
- HNSWインデックス:リコール率 0.991
- HNSW_SQインデックス:リコール率 0.9786
- HNSW_BQインデックス:リコール率 0.9897(ef_search = 1000、refine_k = 10)
1000万件のデータ量の詳細
1000万件の768次元ベクトルデータ(上記の表に記載されている構築パラメータを使用)を例に、メモリ使用量とリコール率のチューニングを補足説明します。
メモリ使用量:
| インデックスタイプ | 推奨テナントメモリ | 説明 |
|---|---|---|
| HNSW | 160 GB | ベクトルインデックスのメモリサイズの推奨値は76.3 GBです。 |
| HNSW_SQ | 48 GB | ベクトルインデックスのメモリサイズの推奨値は22.6 GBです。 |
| HNSW_BQ | 48 GB | HNSW_BQインデックスは構築時に高精度のベクトルを使用する必要があります。HNSW_BQはデフォルトでHNSW_SQをインデックス構築時のキャッシュとして使用するため、パーティション化されていないテーブルではHNSW_BQが使用するメモリはHNSW_SQと同じです。構築完了後、HNSW_BQインデックスは約5.4 GBのメモリを占有します。 |
リコール率のチューニング:
ef_searchとrefine_k(HNSW_BQのみ)のパラメータを調整することで、より多くのベクトル計算によりリコール率を向上させることができます。ただし、その代償としてクエリ性能が低下する可能性があります。異なるTopNで、以下の表に記載されている推奨値をパラメータに設定できます。リコール率をさらに向上させる必要がある場合は、パラメータ値をさらに大きく設定できます。
注意
リコール率はデータの特性と直接的な関係があります。以下の表に記載されている値は、768次元の標準データセットにおいてリコール率が0.95程度になるよう推奨されている値です。
| TopN | ef_search | refine_k(HNSW_BQのみ) |
|---|---|---|
| Top10 | 100 | 4 |
| Top100(HNSW/HNSW_SQ) | 350 | - |
| Top100(HNSW_BQ) | 1000 | 10 |
IVFシリーズ
| シナリオ | インデックスタイプ | パラメータの推奨 |
|---|---|---|
| 低次元 (384次元以下) |
IVF | 1000万件のデータ量:パーティションテーブルを使用、nlist=3000 1億件のデータ量:パーティションテーブルを使用、nlist=3000 |
| 低コスト (メモリ使用量が極めて少ない) |
IVF_PQ | 100万件のデータ量:nlist=1000、m=ベクトル次元/2 1000万件のデータ量:nlist=3000、m=ベクトル次元/2 1億件のデータ量:パーティションテーブルを使用、nlist=3000、m=ベクトル次元/2 |
クラスタ中心の数と各中心に含まれるデータ量をバランスよく取るため、通常nlistをデータ量の平方根に設定することを推奨します。例えば、1000万件のデータにはnlist=3000程度が適しています。IVF_PQを使用する際は、mパラメータをベクトル次元(dim)の半分に設定することを推奨します。
注意
IVF_PQは高圧縮率の量子化アルゴリズムであり、低次元ベクトルにおけるリコール率の上限が低くなる可能性があります。パフォーマンスの損失を避けるため、IVF_PQは128次元以上のベクトルで使用することを推奨します。
注意
データ量が増加する見込みのシナリオでは、最終的なデータ量に基づいてパラメータを設定することを推奨します。
1000万件のデータ量(パーティションテーブルを使用)
上記の例で1000万件の768次元ベクトルデータを使用し、構築パラメータを上表に示すものとします。この場合のメモリ使用量とリコール率のチューニングを補足説明します。
メモリ使用量:
| インデックスタイプ | インデックスパラメータ | メモリ使用量(構築時使用量/常駐使用量) |
|---|---|---|
| IVF | distance=l2, nlist=3000 | 2.7 GB/ 10.5 MB |
| IVF_PQ | distance=l2, nlist=3000, m=384 | 4.0 GB/ 1.3 GB |
| IVF_PQ | distance=cosine, nlist=3000, m=384 | 2.7 GB/ 11.4 MB |
上表の構築時使用量は、インデックス作成時に一時的に使用するメモリであり、構築完了後に解放されます。常駐使用量は、インデックスが構築完了した後、IVFベクトルインデックスが継続的に使用するメモリです。
IVF_PQインデックスの場合、distance = l2を選択すると、追加の事前計算結果を格納する必要があるため、より多くの常駐メモリを使用します。一方、distance = inner_productまたはcosineを選択すると、常駐メモリの使用量は低くなります。そのため、実際の運用では、メモリリソースを最適化するため、distanceタイプとしてinner_productまたはcosineを優先的に選択することを推奨します。
リコール率のチューニング:
nprobesパラメータを調整することで、より多くのベクトル計算を実行してリコール率を向上させることができます。ただし、その代償としてクエリ性能が低下する可能性があります。異なるTopN値に対応するパラメータの推奨値は以下の表に示されています。リコール率をさらに向上させる必要がある場合は、パラメータ値をさらに大きく設定することができます。
注意
リコール率はデータの特徴と直接的な関係があります。以下の表は、768次元の標準データセットにおいてリコール率が約0.95になるよう推奨されるパラメータ値です。
| TopN | nprobes |
|---|---|
| Top10 | 1 |
| Top100 | 20 |
億件以上のデータ量(パーティションテーブルとの併用)
ベクトルデータ量が億件を超える場合、パーティションテーブルとIVF系インデックスを併用することを強く推奨します。データ規模やnlistパラメータが増加するにつれて、単一のIVFインデックスのクエリ負荷も大幅に増加します。データを複数のパーティションに分割し、各パーティションで小規模なIVFインデックスを構築することで、単一クエリの負荷を効果的に軽減し、パーティションパラレルクエリにより全体のクエリ性能とリコール率を向上させることができます。
複数のパーティションテーブルのシナリオでは、IVFインデックスがローカルインデックスであるため、各パーティションで独立してIVFインデックスを構築します。そのため、nlistの値は各パーティションの平均データ量に基づいて計算することを推奨します。例えば、1億件の768次元ベクトルを10個のパーティションに分割した場合、各パーティションには約1000万件のデータが含まれます。この場合、nlistはsqrt(1000万) = 3162に設定することを推奨します。
1億件の768次元ベクトルデータを例に、上記の表に示されている構築パラメータを使用して、メモリ使用量とリコール率のチューニングを補足説明します。
メモリ使用量:
複数のパーティションのシナリオでは、IVFインデックスがローカルインデックスであるため、各パーティションで独立してIVFインデックスを構築および管理します。そのため、メモリに常駐する総使用量はパーティション数に応じて累積されます。例えば、下表に示されている単一のIVFインデックスのメモリ使用量が10.5 MBの場合、10個のパーティションがあると、総メモリ使用量は10.5 × 10 = 105 MBとなります。
| インデックスタイプ | インデックスパラメータ | メモリ使用量(構築時の使用量/常駐使用量) |
|---|---|---|
| IVF | distance=l2, nlist=3000 | 2.7 GB / 10.5 * 10 MB |
| IVF_PQ | distance=l2, nlist=3000, m=384 | 4.0 GB / 1.3 * 10 GB |
| IVF_PQ | distance=cosine, nlist=3000, m=384 | 2.7 GB / 11.4 * 10 MB |
上記の表において、構築時の使用量とは、インデックス作成時に一時的に使用するメモリを指し、構築完了後にその部分のメモリは解放されます。常駐使用量とは、インデックスが構築完了した後、IVFベクトルインデックスが継続的に使用するメモリを指します。
リコール率のチューニング:
nprobesパラメータを調整することで、より多くのベクトル計算を実行し、リコール率を向上させることができます。ただし、その代償としてクエリ性能が低下する可能性があります。異なるTopNの設定では、下表に示されている推奨値を設定することを推奨します。リコール率をさらに向上させる必要がある場合は、パラメータ値をより大きく設定することも可能です。
パーティションテーブルのシナリオでは、各パーティションで独立してIVFインデックスのクエリが実行されるため、クエリ時に複数のパーティションが関与する場合、各パーティションからTopNの結果を個別に取得し、その後すべてのパーティションの結果を集計・再順序付けを行います。これにより、全体の検索精度が向上し、実際のリコール率は単一パーティションのシナリオよりも通常高い傾向にあります。そのため、複数のパーティションテーブルでは、nprobesパラメータを適切に低めに設定することで、単一パーティションテーブルと同等のリコール率を得ることができます。
注意
リコール率はデータの特性と直接的な関係があります。下表に示されている値は、768次元の標準データセットにおいて、リコール率が約0.95になるよう推奨される値です。
| TopN | nprobes |
|---|---|
| Top10 | 1 |
| Top100 | 10 |
関連ドキュメント
- パラメータの詳細な説明とチューニングについては、HNSWインデックスとIVFインデックスを参照してください