メインコンテンツまでスキップ
に最終更新

Lance クエリのベストプラクティス

このガイドを使用して、Lance クエリの BE ごとのキャッシュ予算とインデックスセグメントのレイアウトを選択します。まずワークロードを確認し、キャッシュに保持する必要があるデータ量を見積もり、想定する同時実行数で検証します。ここで示す例は容量計画の出発点であり、ベンチマーク済みの最適値や BE のメモリ上限ではありません。

注記

Lance Catalog は実験的機能であり、Apache Doris 4.2 以降でサポートされています。まず Lance Catalog を使用してアクセスを設定し、Reader の互換性を確認してください。Doris は既存の Lance インデックスを読み取ります。インデックスの構築や保守には、互換性のある Lance ツールを使用してください。

スカラーフィルターをベクトル検索または全文検索と組み合わせる場合は、フィルターの配置、整合したインデックス構築、Profile の診断について Lance Hybrid Search Performance Best Practices を参照してください。

1. 調整方法を選択する​

ワークロード開始点検証内容
単一クエリのレイテンシーが低いベクトル検索頻繁に検索されるベクトルパーティションを保持し、セグメントガイドを使用して、利用可能な BE 数に対してバランスの取れたセグメント数を比較する同程度の再現率での P95 レイテンシー、最も遅いスキャナー、ピークメモリ
高同時実行ベクトル検索異なるクエリベクトルがアクセスするホットパーティションの和集合に予算を割り当て、各クエリの分割数を最大化するのではなく、同時実行検索のためにメモリと CPU を確保する目標同時実行数でのスループットと P95 レイテンシー、キャッシュの再読み込み、BE ごとのメモリ
BTree の範囲/ポイントフィルター、または Bitmap/LabelList フィルタールックアップ構造を含むホットページまたはビットマップエントリを見積もり、述語/インデックスが使用されていることを確認するページロード、選択率、一時的な行 ID セット、出力列の読み取り
全文検索またはフレーズ検索有効化されている場合は辞書、ドキュメントメタデータ、転置リスト、位置情報を見積もり、ウォームアップに多様な語句を含める一般的な語句のクエリ、フレーズクエリのメモリ、候補のマージ
ベクトル、スカラー、全文クエリが BE を共有する各クエリの共有ワーキングセットを加算して一緒にテストするあるクエリ種別が別のクエリ種別のエントリを追い出していないか
出力列の取得またはスキャンが支配的データファイルの読み取りと独立したディスクデータキャッシュを調べる有効バイト数と読み取り増幅、デコードまたは取得が支配的かどうか

スカラーフィルターはベクトルクエリの Prefilter の一部になる場合もあるため、1 つのクエリがスカラーとベクトルの両方のインデックス内容を必要とすることがあります。シナリオを相互排他的とみなさず、該当する行をすべて選択してください。

2. 入力を収集してメモリ予算を設定する​

各 BE について、または現実的な配置条件で代表的な BE を選び、次の入力を収集します。

  • ワークロード: 目標 QPS/同時実行数、レイテンシー目標、必要な再現率、top_k、フィルター、フレーズクエリ、出力列。
  • リソース: クエリに使用できる BE、CPU 容量、他の Doris ワークロードとプロセス/OS の要件を差し引いた後に使用できるメモリ。
  • インデックス: 種類、バージョン、物理セグメント数、カバレッジ、ベクトルの次元数/エンコーディング、IVF パーティション数、スカラー値の幅または文字列長。
  • 再利用: 代表的なクエリ期間にアクセスされる異なるパーティション、ページ、語句、またはビットマップエントリ。1 つのクエリが返す行数ではなく、クエリ間のワーキングセットを使用します。
  • クエリのピーク: 想定する同時実行数でのアクティブなパーティションロード、Prefilter/結果の行 ID セット、候補ヒープ、デコード、再ランキング、二段階目の取得に必要なメモリ。

index formulasを使用してペイロードを見積もり、合計予算が次を満たすことを確認します。

available_Lance_cache_budget_on_BE
= BE memory budget
- other BE memory needs
- peak concurrent query working memory
- safety headroom

index_cache_target + metadata_cache_target
<= available_Lance_cache_budget_on_BE

これは計画上の確認であり、強制的なメモリ予約ではありません。キャッシュ容量はクエリメモリやプロセス RSS を制限しません。再利用可能なキャッシュワーキングセットに同時実行クエリ数を掛けてはいけません。代わりに、クエリが追加で使用するワーキングメモリを予約し、同時実行クエリが異なるデータにアクセスする場合は、キャッシュ対象データの和集合が大きくなることを考慮します。

パラメーターの定義とデフォルト値は BE Configuration にあります。各 BE の be.conf に lance_* BE パラメーターを設定し、その BE を再起動します。これらは Catalog プロパティや SQL セッション変数ではありません。インデックスセグメント数と IVF 構築パラメーターは Lance のインデックス構築ツールで設定し、これらのキャッシュパラメーターでは設定しません。

3. インデックスのワーキングセットを見積もる​

各 BE が再利用する必要のあるインデックスパーティションを対象に、インデックスキャッシュのサイズを設定します。ストレージ上のインデックス全体、キャッシュされたワーキングセット、クエリのピークメモリは異なる量です。以下の見積もりは、Doris がサポートする 6 種類のベクトルインデックスタイプを対象としています。これらは計画用の見積もりであり、正確なキャッシュ計測値やメモリ上限ではありません。

インデックスタイプごとのベクトルペイロード​

次の記号を使用します。すべての式はバイト単位で、1 GiB = 1073741824 bytes です。

記号意味
N見積もり対象パーティションに含まれるインデックスベクトル数。通常の単一ベクトル列では、インデックス化された行数です。マルチベクトル列では、インデックス化されたサブベクトルを数え、行マッピングと再ランキング用に別途予算を確保します。
Dベクトルの次元数。
w保存された非量子化ベクトル要素あたりのバイト数。Float16 は 2、Float32 は 4、Float64 は 8。バイナリ uint8 ベクトルでは実際のバイト長を D とし、w=1 とします。
m、bPQ サブベクトル数と、サブベクトルコードあたりのビット数。これらはインデックス構築設定であり、クエリパラメーターではありません。
Gロードされた HNSW グラフが占有するメモリ。すべてのレベルと補助構造を含みます。

該当するコンポーネントをすべて加算し、ベクトルコードだけを計算しないでください。 最初の表ではベクトルごとのペイロードを分けています。続く表では共有構造と HNSW グラフのコンポーネントを示します。すべての式はロード済みバッファーを見積もります。Measure と記された行も予算に含める必要があり、ゼロコストではありません。共有アロケーションは 1 回だけ数えます。

インデックスタイプベクトル値 / コードUInt64 行 IDHNSW グラフその他の必要な予算
IVF_FLATN * D * w8 * Nなし下記の IVF 構造 + 共通オーバーヘッド
IVF_SQSQ8 の場合 N * D8 * NなしIVF 構造 + SQ メタデータ + 共通オーバーヘッド
IVF_PQN * ceil(m * b / 8)8 * NなしIVF 構造 + PQ コードブック + 共通オーバーヘッド
IVF_HNSW_FLATN * D * w8 * NG を追加IVF 構造 + 共通オーバーヘッド
IVF_HNSW_SQSQ8 の場合 N * D8 * NG を追加IVF 構造 + SQ メタデータ + 共通オーバーヘッド
IVF_HNSW_PQN * ceil(m * b / 8)8 * NG を追加IVF 構造 + PQ コードブック + 共通オーバーヘッド

PQ で b=8 の場合、コードはベクトルごとに m バイトを占有します。b=4 の場合、サポートされる偶数の m では m/2 バイトを占有します。たとえば、100 万ベクトルで m=96、b=8 の場合、コードは 96000000 バイト、行 ID は 8000000 バイトで、合計は 104000000 バイト(約 99.2 MiB)です。強く圧縮されたインデックスの見積もりでも、行 ID を省略してはいけません。

追加コンポーネント適用対象ロード済みペイロード / 予算方法
IVF セントロイド6 種類すべて保持するセントロイドセットごとに FP32 で num_partitions * D * 4。その他のレイアウトでは実際の要素幅を使用
IVF パーティションディレクトリ / サブインデックスメタデータ6 種類すべてMeasure 保持されるパーティションのオフセット、長さ、Reader 構造。ベクトル値やセントロイドとは別
PQ コードブックIVF_PQ、IVF_HNSW_PQ保持する標準 FP32 コードブックごとに 2^b * D * 4
SQ 量子化器メタデータIVF_SQ、IVF_HNSW_SQMeasure 保持される量子化器の境界/パラメーター。バージョン間で固定レイアウトと仮定しない
ノルム、行カバレッジ構造、追加マッピングReader が保持する場合Measure 実際の配列/セット。マルチベクトル行マッピングには別予算が必要
インデックスオブジェクト、Arrow validity バッファー、余剰容量、コピー6 種類すべてMeasure 論理ペイロード以外のアロケーション。共有バッファーは 1 回だけ数える

独立したインデックスセグメントは、別々のセントロイドセットとコードブックを保持する場合があります。共有アロケーションをパーティションごとに重複して計算したり、すべてのコピーが共有されると仮定したりしないでください。追加構造は、組み込まれている Lance バージョンに依存します。

HNSW グラフコンポーネント​

グラフはベクトルコードと行 ID に追加して計上します。 UInt32 のノード/隣接ノード ID と、保持される場合は Float32 のエッジ距離を持つ Arrow ベースの Lance グラフについて、ロードされたすべてのレベルにわたる保存済み有向隣接エントリ数を E、それらのレベルにおけるノード出現数を V、独立して保持されるグラフバッチ数を A とします。複数のレベルに存在するノードは、V に複数回加算されます。

グラフコンポーネント主なペイロード(バイト)カウント方法
隣接ノード ID4 * E有向隣接エントリごとに UInt32。すべてのレベルを数える
保存されたエッジ距離4 * E隣接エントリごとに Float32。Reader が距離列をスキップする場合はゼロ
グラフノード ID4 * Vノード出現ごとに UInt32。データセットの UInt64 行 ID とは別
隣接リストオフセット4 * (V + A)Int32 のリストオフセット。各バッチに終端オフセットを 1 つ含む
距離リストオフセット4 * (V + A)2 番目の Int32 リストオフセット配列。Reader が距離列をスキップする場合はゼロ
距離を含む小計8 * E + 12 * V + 8 * A大きなバッチでは約 8 * E + 12 * V。完全な G ではない
距離を含まない小計4 * E + 8 * V + 4 * Aノード ID と隣接リストだけを保持する場合に使用。2 つの小計を両方加算しない
レベルオフセット、エントリポイント、ノード検索構造Measureロードされた各グラフの保持メタデータと検索アロケーションを含める
Validity バッファー、グラフオブジェクト、余剰アロケーション容量Measure上記バッファー以外の実際のアロケーションを加算し、共有バッファーを二重計上しない
完全なグラフ予算 G主な小計 + 実測したグラフ追加分ベクトル/行 ID ペイロードやその他のインデックス構造に加算する

これはレイアウト固有の見積もりであり、ノードあたりの固定バイト数を保証するものではありません。HNSW の m はグラフの接続性を制御し、PQ の m とは無関係です。G の代わりに N * m * 4 を使わないでください。実際の次数、上位レベル、保持される距離、Reader のバージョンが影響します。代表的なパーティションをロードし、保持されるアロケーションを測定して調整してください。

たとえば、キャッシュされた IVF_HNSW_PQ パーティションに 100 万ベクトルがあり、PQ が m=96、b=8、E=32000000、V=1100000、A=1 だとします。この Reader が距離列を保持すると仮定します。これらのグラフ値は説明用の入力であり、HNSW の m から導出されたものではありません。

コンポーネント例のペイロード
PQ コード96000000 バイト
データセット行 ID8000000 バイト
主なグラフバッファー8 * 32000000 + 12 * 1100000 + 8 = 269200008 バイト、約 256.7 MiB
コード + 行 ID + 主なグラフバッファー373200008 バイト、約 355.9 MiB
代替: 距離をスキップした場合の主なグラフバッファー4 * 32000000 + 8 * 1100000 + 4 = 136800004 バイト、約 130.5 MiB
代替合計: コード + 行 ID + 距離なしのグラフバッファー240800004 バイト、約 229.6 MiB
いずれの場合も追加するもの上表のグラフ追加分、IVF セントロイド/ディレクトリ、PQ コードブック、共通オーバーヘッド

Reader が保持する列に一致する例を選択してください。どちらの小計も、完全なキャッシュ容量の推奨値ではありません。

上流の Lance Performance Guide では、ベクトルペイロードとインデックス構築メモリの見積もりを説明しています。Lance vector index format では、IVF パーティション、サブインデックス、量子化ストレージの分離について説明しています。最新の内容には、Doris に組み込まれた Lance バージョンより新しい機能が記載されている場合があります。互換性については Lance Catalog のサポートマトリックスを使用してください。

スカラーおよび全文インデックスのペイロード​

スカラーインデックスも見積もれますが、入力はインデックスファミリーごとに異なります。クエリが返す行だけでなく、1 つの BE に実際に保持されるエントリを数えます。以下の方法は Lance のストレージレイアウトを説明するものであり、Doris の述語プッシュダウンやインデックス互換性の保証を拡張するものではありません。組み込まれた Lance バージョンがそのインデックスをサポートしていることと、クエリが実際にそれを使用していることを確認してください。

BTree。 ロードされたリーフページには値と UInt64 行 ID が含まれます。キャッシュされたリーフページ内のレコード数を R、そのページ数を H、固定幅の値サイズを w、それらのページ内の平均文字列長をバイト単位で L とします。

リーフページのコンポーネント / 表現値バッファーオフセットUInt64 行 ID
Int32 / Float324 * Rなし8 * R
Int64 / Float64 / 64 ビットタイムスタンプ8 * Rなし8 * R
その他の固定幅値w * R; ビットパックされた Boolean には実際のビットマップバッファーを使用なし8 * R
Arrow Utf8 / BinaryR * LInt32 オフセットの場合 4 * (R + H)8 * R
Arrow LargeUtf8 / LargeBinaryR * LInt64 オフセットの場合 8 * (R + H)8 * R

リーフページの小計は、3 つのペイロード列の合計です。 開かれた各セグメントについて、次のコンポーネントを追加します。ここで P はそのセグメント内のすべてのリーフページ数であり、キャッシュされたページだけではありません。

追加の BTree コンポーネント主なペイロード / 予算方法
ルックアップの最小値固定幅値の場合は P * w。可変幅値の場合は実際の値/オフセットバッファー
ルックアップの最大値固定幅値の場合は P * w。可変幅値の場合は実際の値/オフセットバッファー
ルックアップ NULL カウントUInt32 レイアウトの場合 4 * P
ルックアップページ番号UInt32 レイアウトの場合 4 * P
固定幅ルックアップバッファーの小計P * (2 * w + 8)。下記の構造を除く
NULL ページリストとルックアップオブジェクトMeasure 保持されるリスト、オブジェクト、実装固有のコピー
リーフ/ルックアップ validity バッファー、Arrow オブジェクト、余剰容量Measure 論理値/オフセット/行 ID 以外のアロケーション

文字列の式は、表に示した Arrow レイアウトを前提としています。辞書または view 表現では、実際のバッファーを使用してください。ディスク上の圧縮サイズは、デコード後のページサイズを決定しません。BTree のデフォルトページサイズは 4096 レコードであり、バイトではありません。インデックスの実際のページサイズを使用してください。ルックアップはインデックスワーキングセットに属するため、ページを記述するという理由だけで BE メタデータキャッシュの予算に入れてはいけません。

たとえば、1 億個の Int64 値には、リーフ値/行 ID ペイロードとして 100000000 * 16 = 1600000000 バイト(約 1.49 GiB)があります。キャッシュされたページが 1000 万レコードをカバーする場合、そのペイロードは約 152.6 MiB です。1 ページあたり 4096 レコードとすると、インデックス全体には約 24415 ページがあります。ルックアップバッチの min/max/count/page-number ペイロードは、追加構造を除いて約 572 KiB です。10 件の一致行が返されても、10 レコードだけがキャッシュされるわけではありません。Reader はページをロードします。

Bitmap、LabelList、NGram。 下表の該当するコンポーネントを合計します。メンバーシップビットマップのコストを、一致する行ごとに 8 バイトと自動的に見積もってはいけません。LabelList は異なるラベルごとにメンバーシップを数えるため、1 行が複数のラベルビットマップに現れることがあります。NGram は異なる gram/行メンバーシップを数えます。1 行内で同じ gram が繰り返し出現しても、メンバーシップは増えません。この NGram インデックスは、n-gram トークナイザーを使用する FTS インデックスとは異なります。

インデックスファミリーコンポーネントロード済みペイロード / 予算方法
BitmapキールックアップMeasure 保持されるキー値、エントリ参照、ルックアップオブジェクト
LabelListラベルルックアップ / ラッパーMeasure 異なるラベルキー、エントリ参照、ラッパーオブジェクト
NGramGram ルックアップMeasure 保持される gram、エントリ参照、ルックアップオブジェクト
3 種類すべてメンバーシップビットマップ: 配列コンテナ65536 値の範囲で c 個の UInt16 エントリを持つ通常の Roaring 配列コンテナでは約 2 * c
3 種類すべてメンバーシップビットマップ: 密コンテナ65536 値の範囲をカバーする通常の密コンテナでは 8192 バイト
3 種類すべてメンバーシップビットマップ: run / 完全フラグメント表現Measure 実際の表現。各コンテナで選択された表現だけを使用し、すべての代替表現を合計しない
3 種類すべてビットマップディレクトリ / 容量Measure フラグメント/上位ビットディレクトリ、コンテナオブジェクト、余剰容量
存在する場合NULL / null-list 追跡Measure 保持される NULL メンバーシップ構造を別途計上
各ファミリーの合計ルックアップ + ロード済みメンバーシップ表現 + ディレクトリ + NULL 追跡共有アロケーションは 1 回だけ数える。シリアライズされたビットマップサイズは常駐メモリを保証しない

たとえば、256 個のロード済み密コンテナには 2 MiB のビットセットペイロードがあります。これはキー、ディレクトリ、NULL 追跡、オブジェクトオーバーヘッドを含みません。

その他のスカラーおよび全文インデックス。 各行は別個のコンポーネントを示します。小計行は前のコンポーネントをまとめたものであり、再度加算してはいけません。BE に保持される内容だけを数えます。Measure は Reader の実際のアロケーションが必要という意味であり、そのコンポーネントを省略できるという意味ではありません。

インデックスファミリーコンポーネントロード済みペイロード / 予算方法
FTS / Inverted用語辞書Measure ロードされる用語、辞書構造、ルックアップアロケーション
FTS / InvertedドキュメントメタデータMeasure 保持されるドキュメントマッピング、長さ、その他の Reader メタデータ
FTS / Invertedプレーン転置行 IDT 個の UInt64 用語/ドキュメントエントリでは 8 * T
FTS / Invertedプレーン転置頻度Float32 頻度では 4 * T。ID + 頻度の合計は 12 * T
FTS / Inverted位置情報(有効な場合)保存された O 個の Int32 出現位置では 4 * O
FTS / Inverted位置オフセット実際に保持されるオフセット配列のバイト数。4 * O とは別
FTS / Inverted圧縮転置レイアウト対応するプレーンレイアウトの式の代わりに、実際に保持される圧縮ブロックを使用
FTS / Invertedスコアリング/ブロックメタデータとアロケーションオーバーヘッドMeasure 保持されるブロック記述子、スコアリングデータ、オブジェクト、余剰容量
ZoneMap最小値ロードされた Z 個のゾーンと幅 w の固定幅値では、論理バイト数 Z * w
ZoneMap最大値論理バイト数 Z * w。min + max の合計は 2 * Z * w
ZoneMapカウントとゾーン境界Measure 保持されるカウントと境界。部分ゾーンを含め、Fragment ごとにゾーンを数える
ZoneMapNULL 追跡とボックス化値/オブジェクトオーバーヘッドMeasure オプションの NULL 行セットと実際のスカラーアロケーション。論理的な min/max バイト数を上回る場合がある
BloomFilterフィルタービット配列実際に割り当てられたフィルターバイトを合計。F バイトの同じサイズのフィルターが Z 個なら Z * F
BloomFilterゾーン記述子 / フィルターオブジェクトMeasure 保持される記述子、フィルターパラメーター、オブジェクトオーバーヘッド
BloomFilterNULL 追跡Measure オプションの NULL 行セット
RTreeバウンディングボックス座標2D エントリごとに 4 つの Float64 座標で 32 * Q。Q はキャッシュされたすべてのツリーレベルのエントリ数
RTree行 / 子ページ IDUInt64 ID では 8 * Q。座標 + ID の合計は 40 * Q
RTreeツリーメタデータとページオフセットMeasure 保持されるツリー記述子とページオフセットバッファー
RTreeNULL 追跡、Arrow/オブジェクト、余剰容量Measure 実際の追加アロケーション
JSON-path ラッパー基盤となるインデックス選択したスカラーインデックスファミリーの完全なコンポーネント予算を使用
JSON-path ラッパーパスとラッパー構造Measure 基盤となるインデックスに加えて保持されるパスとラッパーのアロケーション

Bloom フィルターでは、ビルダーが実際にブロック単位で丸めて割り当てたサイズを使用する必要があります。行数と偽陽性率だけでは、すべてのレイアウトを説明できません。未知または実験的なレイアウトでは、別のファミリーの式を適用せず、ロード済みアロケーションを測定してください。一致する行が少なくても、辞書、ツリー、ドキュメントメタデータに相当な容量が必要になることがあります。

クエリのワーキングメモリは、すべてのキャッシュ表とは分けてください。 一時的な積集合/和集合、結果行 ID セット、近似フィルターの再確認、正確な RTree チェックのための元のジオメトリ読み取り、出力列の読み取りには、それぞれ独自の予算が必要です。

基盤構造については、上流の BTree format、Bitmap format、FTS format を参照してください。上記の式はロード済みペイロードを見積もるものであり、圧縮ファイルサイズやクエリ全体の RSS ではありません。

インデックスサイズから BE ごとのワーキングセットへ​

セグメント s について、そのインデックス化されたベクトル数を N_s、IVF パーティション数を P_s、特定の BE に保持する異なるパーティション数を H_s とします。パーティションが十分に均衡している場合は、次のようになります。

cached_vectors_on_BE ≈ sum over segments (N_s * H_s / P_s)
index_cache_target ≈ cached vector/row-ID payload
+ cached HNSW graphs
+ centroids, codebooks and other index allocations
+ measured headroom

パーティションに偏りがある場合は、実際のパーティション行数を使用します。H_s はクエリ間のワーキングセットを表し、1 つのクエリの nprobes だけを表すものではありません。多様なクエリは最終的にすべてのパーティションに触れる可能性があります。繰り返しクエリや同時実行クエリは同じキャッシュ済みパーティションを共有できます。(dataset, index segment, partition) の異なる組み合わせを数え、その BE がアクセスするすべてのテーブル、インデックス、バージョンを含めます。1 つの BE のキャッシュで別の BE がウォームアップされることはなく、スケジューリングによってすべてのインデックスセグメントが常に同じ BE に配置される保証もありません。観測された配置と再利用状況が正当化しない限り、インデックス全体のサイズを BE 数で割らないでください。

クエリ時のメモリは別途必要です。インフライトのパーティションロード、キャッシュから追い出された後もクエリが保持するオブジェクト、Prefilter の状態、距離テーブル、候補ヒープ、デコード済みバッチ、再ランキング、二段階目の取得などです。top_k、ef、refine_factor、スキャン同時実行数、nprobes はこのメモリやアクセスされるワーキングセットに影響しますが、ベクトルあたりの保存バイト数は変えません。設定したキャッシュ容量は Lance や BE の RSS に対するハード上限ではありません。キャッシュを増やしても、距離計算やクエリごとのフィルタリング処理はなくなりません。

構成例と調整​

1 つのインデックスセグメントに、FP32、768 次元の IVF_PQ インデックスがあり、1 億ベクトル、m=96、b=8、均衡した 4096 パーティションがあるとします。1 つの BE の代表的なワークロードが 1024 個の異なるパーティションに繰り返しアクセスするとします。

Full code/row-ID payload = 100000000 * (96 + 8) = 10400000000 bytes ≈ 9.69 GiB
Cached payload = 10400000000 * 1024 / 4096 = 2600000000 bytes ≈ 2.42 GiB
IVF centroids = 4096 * 768 * 4 = 12582912 bytes = 12 MiB
PQ codebook = 256 * 768 * 4 = 786432 bytes = 0.75 MiB

これが BE 上で唯一の大規模なインデックスワーキングセットで、メモリ予算が許す場合、この例では 4 GiB を初期インデックスキャッシュ割り当てとして設定するのが妥当です。計算されたペイロードに加えて、追加のインデックスアロケーション分を残せます。これは検証すべき初期値であり、普遍的なオーバーヘッド比率ではありません。ワークロードがインデックス全体を常駐させる必要がある場合、4 GiB では不足します。デフォルトの 10 GiB でさえ、他のアロケーションを含める前の 9.69 GiB のペイロードに近い値です。

4 GiB のインデックスキャッシュと 1 GiB のメタデータキャッシュを、ピーククエリメモリ、他の Doris ワークロード、プロセス/OS の余裕とともに収められる BE では、次を設定します。

lance_index_cache_size_bytes = 4294967296
lance_metadata_cache_size_bytes = 1073741824

これらの設定を有効にするには、その BE を再起動します。予算は各 BE に個別に適用します。これらは BE 構成パラメーターであり、Catalog プロパティや SQL セッション変数ではありません。

  1. 異なるクエリベクトル、フィルター、テーブルを含む代表的なクエリと同時実行数でウォームアップします。1 つのベクトルだけを繰り返すと、多様なワークロードのワーキングセットを過小評価します。
  2. doris_be_lance_session_index_cache_usage_bytes と doris_be_lance_session_index_cache_capacity_bytes を比較し、期間内の hits_total/misses_total の増加量を観測します。完了した各クエリについて、LanceIndex 内の LanceIndexCacheHits、LanceIndexCacheMisses、LanceIndexObjectLoads、LanceIndexComponentsLoaded も確認します。クエリキャッシュのルックアップとコンポーネントロードはスコープが異なり、BE 全体のメトリクス差分と同じものではありません。使用量が容量に近い状態でミスが続く場合、キャッシュの競合が示唆されることがあります。ただし、新しいパーティション、インデックスバージョン、異なる BE、保持されない内容を扱うストリーミングパスもミスを引き起こします。再利用と利用可能なメモリが正当化する場合にだけ容量を増やしてください。
  3. BE のメモリ予算が許す場合は、メタデータキャッシュのサイズをデフォルトの 1 GiB から開始します。その usage_bytes とヒット/ミスメトリクスを使用して調整します。ファイル/Fragment 数、スキーマ/ページメタデータ、削除情報、行 ID マッピングによって必要量が決まります。ベクトルインデックスサイズの一定割合ではありません。BE のメタデータキャッシュは FE のテーブルアクセスキャッシュとは別です。
  4. どちらかのキャッシュを増やす前に、想定する同時実行数で BE プロセスメモリとクエリピークを確認します。キャッシュヒット率が高くてもレイテンシーが高い場合、スコアリング、Prefilter、デコード、取得のコストが原因かもしれません。キャッシュを追加しても必ずしも有効とは限りません。
  5. 再ランキングや出力列の取得など、データファイルを繰り返し読み取る処理については、lance_data_cache_disk_capacity_bytes を独立して設定します。これを増やしてもインデックスキャッシュは拡大せず、インデックスキャッシュミスを補うこともできません。インデックスファイルはこのディスクデータキャッシュをバイパスします。lance_data_cache_read_block_size_bytes は最初はデフォルトの 1 MiB のままにし、有効な読み取りと読み取り増幅を測定した後で変更します。

4. 共有キャッシュの予算を設定する​

各 BE で Lance は共有セッションと 1 つのインデックスキャッシュ容量を使用します。ベクトルパーティション、BTree ページ、Bitmap/LabelList エントリ、全文インデックスの内容は、この領域を競合します。同じ BE でアクセスされる異なるテーブルや Catalog のインデックスも含まれます。キャッシュキーは ID を分離しますが、容量を予約するものではありません。Lance の BE キャッシュ設定には、テーブル単位またはインデックスタイプ単位のクォータや固定保持を制御する機能はありません。

キャッシュ容量を消費するのはロード済みの内容だけです。複数のインデックスを作成しただけで、それらがすべてロードされるわけではありません。クエリが使用を開始すると、1 つのインデックスをロードすることで別のインデックスのエントリが追い出されることがあります。たとえば、広い範囲の BTree スキャンや多様な FTS クエリによって、ウォーム状態だったベクトルパーティションが置き換えられる場合があります。その後のベクトルクエリでは、再度ロードが必要になります。インデックスバージョンの変更により、古いエントリが常駐している間に新しいエントリが追加されることもあります。実行中のクエリが参照しているオブジェクトは、追い出されてもすぐには解放されません。

共有アロケーションを二重計上せず、混合ワーキングセットを計画します。

index_cache_target_on_BE ≈ vector working set
+ BTree working set
+ Bitmap / LabelList / NGram working sets
+ FTS and other index working sets
+ measured headroom

たとえば、測定とペイロードの見積もりにより、ベクトルが 2.5 GiB、BTree が 0.25 GiB、Bitmap が 0.5 GiB、FTS が 0.75 GiB で、それぞれのインデックス構造を含むとします。合計ワーキングセットは 4 GiB です。5 GiB の初期インデックスキャッシュは、増加分と見積もり誤差として 1 GiB を残しますが、すべてのワークロードが収まることを保証するものではありません。BE に 1 GiB のメタデータキャッシュ、およびピーククエリメモリ、他の Doris ワークロード、プロセス/OS の余裕を収める余地がある場合は、次を設定します。

lance_index_cache_size_bytes = 5368709120
lance_metadata_cache_size_bytes = 1073741824

インデックスキャッシュとメタデータキャッシュの容量は別々です。メタデータエントリがインデックスエントリを直接追い出すことはなく、一方を増やしても他方は拡大しません。ただし、どちらも同じ BE プロセスのメモリを消費します。ディスクデータキャッシュは 3 つ目の予算であり、インデックスファイルはキャッシュしません。同じ BE 上で Catalog を分けてもインデックスキャッシュは分離されません。分離が必要なワークロードでは、デプロイメントがサポートする別個の BE リソースとルーティングを使用します。

競合を診断するには、まず 1 つのクエリファミリーをウォームアップしてレイテンシーとキャッシュメトリクスの差分を記録します。次に 2 つ目のファミリーを実行し、最初のファミリーを再実行します。インデックスバージョンと BE の配置が同等で、キャッシュ使用量が容量に近い状態でミスや再ロードが再び発生する場合は、追い出し圧力が示唆されます。セッションのヒット/ミスメトリクスはワークロードを集約するため、クエリレベルの LanceIndexCacheHits/LanceIndexCacheMisses、LanceIndexComponentsLoaded、LanceIOReadBytes と組み合わせて確認します。コンポーネントロード数はミス数ではなく、実行時の読み取りバイト数は実測したリモートトラフィックではありません。すべてのインデックスを事前ウォームアップすると、保持したかったワーキングセット自体が追い出される可能性があります。代表的な混合ワークロードでウォームアップし、再利用と利用可能なメモリが正当化する場合にだけ容量を増やしてください。

5. インデックスセグメントの粒度を選択する​

インデックスセグメント、データ Fragment、IVF パーティション、BTree リーフページは異なる単位です。現在の Doris ベクトル検索パスでは、選択された各物理インデックスセグメントが 1 つのスキャン Split になり、カバレッジのない Fragment は Flat Search Split を追加します。FTS も物理インデックスセグメントを使用します。1 つのベクトルセグメント内の IVF パーティションが、複数の BE に分散される個別の Doris Split になることはありません。ただし、Lance は内部で処理を並列実行できます。通常のスカラー走査でセグメントに基づくグループ化が行われるかどうかは、選択したインデックスとプランによって異なります。すべてのスカラーインデックスがベクトル検索と同じ Split ポリシーに従うと仮定しないでください。

B をこのクエリで実際に使用できる BE 数、S を選択されたベクトルセグメント数とします。S が B より少ない場合、そのクエリには、すべての BE を使用するのに十分なインデックススキャン Split がありません。S を増やすとスケジューリングの機会は増えますが、すべての Split が同時に実行される保証はありません。スキャナーの制限、Lance の内部同時実行数、CPU、I/O、キャッシュ常駐、同時実行クエリも影響します。Doris のパイプラインインスタンスだけを増やしても、1 つのインデックスセグメントを分割することはできません。

大規模なデータセットでは、適度に均衡した B、2 * B、4 * B 個のベクトルセグメントを、公式の最適値や小規模データセットに対する要件ではなく、初期実験として比較します。8 個の利用可能な BE と 1 億ベクトルの例を示します。

セグメント数セグメントあたりの平均ベクトル数評価内容
812.5 millionBE をカバーするのに十分な Split で、セグメントあたりの処理が少ない
166.25 millionスケジューリングの柔軟性が高く、1 つの大きなセグメントへの依存が小さい
323.125 millionタスク数が増えるが、検索、ロード、マージのオーバーヘッドが増える可能性がある

Fragment 数だけでなく、推定検索処理量とロード済みインデックスバイト数を均衡させます。同じ次元数とエンコーディングのベクトルでは、行数を均衡させることが出発点になります。HNSW グラフサイズ、IVF の偏り、スカラー選択率、ドキュメント長によってバランスが変わる場合があります。セグメントあたりの行数やファイルサイズに普遍的なしきい値はありません。高スループットのワークロードでは、同時実行クエリの容量を確保するために、クエリあたりのタスクを少なくする方が適する場合があります。単一クエリのレイテンシーは、Split を増やすことで改善する場合があります。

セグメントが増えると、セグメントごとのセットアップ、メタデータ/量子化器オブジェクト、ローカル候補生成も増えます。各ベクトル/FTS Split は最大 top_k + offset 個の候補を保持し、Doris はこの上限を S で割りません。したがって、スキャン側の候補上限は S * (top_k + offset) であり、実際の一致数に制限されます。top_k=1000、offset なし、32 Split の場合、Doris の削減前に最大 32000 個の候補があります。ローカル TopN によりネットワーク転送量は減る可能性があるため、これはネットワーク行数の保証ではありません。top_k が大きい場合は、候補処理が特に重要になります。

セグメント数は、各セグメントの IVF num_partitions およびクエリの nprobes と併せて調整します。均衡したパーティションでは、探索されるベクトル数の概算は sum(N_s * nprobes_s / P_s) であり、各セグメントでは N_s が上限になります。これは HNSW の比較回数の式ではありません。セグメントを再構築したりパーティション数を変更したりすると、同じ nprobes でも再現率が変わる可能性があります。再現率が同程度になる条件でレイテンシーを比較します。HNSW の ef と再ランキング設定も比較に影響します。

Lance ツールでセグメントを構築・保守し、目的の論理インデックスとしてコミットします。別名で作成した複数の全テーブルインデックスは、複数の物理セグメントを持つ 1 つのインデックスの代わりにはなりません。完全な Fragment のグループでバランスを取り、小規模な追加による小さなセグメントの蓄積を避け、組み込まれた Lance バージョンがサポートする保守 API を使用します。構築後、Doris の EXPLAIN/Profile で物理セグメント数とカバレッジのない Fragment 数を確認してください。SHOW INDEX の行数から推測しないでください。すべてのセグメントを 1 つにマージすると、Doris のスキャン並列性が低下する可能性があります。セグメントの構築とコミットの概念については Lance distributed indexing を参照してください。

BTree のポイントルックアップや選択性の高い Bitmap クエリでは、多数のセグメントに分割するとルックアップとオープン処理が増える一方、セグメントあたりの削減作業が少ないことがあります。FTS では、セグメントごとの辞書/転置検索と候補マージが追加されます。ベクトルのセグメント数をすべてのインデックスファミリーに適用せず、これらのワークロードを個別に評価してください。分割しても、行ごとに不要な Prefilter を構築する処理はなくなりません。Reader のフィルタリング動作を個別に確認してください。

6. 混合ワークロードを検証する​

  1. インデックス選択、物理 Split、インデックスカバレッジを確認します。フォールバック走査と二段階目の取得をレイテンシー分析に含めます。
  2. 各インデックスの保持ペイロードを見積もり、共有ワーキングセットを加算します。並列ロード、行 ID セット、候補ヒープ、デコードを含むクエリメモリは別途確保します。
  3. 現実的な同時実行数で、コールドキャッシュとウォーム済みの混合ワークロードを比較します。P95 レイテンシー、スループット、該当する場合は再現率、BE ごとのピークメモリ、キャッシュ使用量とヒット/ミスの差分、インデックスロード I/O、スキャン時間の偏りを追跡します。
  4. 一度に 1 つの軸だけを変更します。キャッシュ容量、セグメント数、検索パラメーターのいずれかです。セグメントの再構築でモデルが変わった場合は、再現率を再確認します。スループット、レイテンシー、メモリが改善しなくなったら、Split やキャッシュを増やすのを停止します。
  5. 大幅な追加、インデックス再構築、BE のスケーリング、クエリ構成の変更後に再評価します。1 つのベクトルやテーブル向けに調整した構成は、すべてのワークロードに対する安定した予算ではありません。

7. リソースを増やす前に診断する​

観測結果最初に確認すること評価する対策
キャッシュ使用量が容量に近い状態でインデックスミスが繰り返されるインデックス/バージョンの変更、BE 配置、合計ワーキングセットメモリが許せば lance_index_cache_size_bytes を増やす、不要なウォームアップを減らす、または別の BE リソースにワークロードを分離する
スカラーまたは FTS クエリの後にベクトルクエリが遅くなる共有キャッシュの予算でクロスワークロードの追い出しを再確認する両方のクエリファミリーを合わせて予算化する。同じ BE 上の別 Catalog はキャッシュを分離しない
大規模なインデックスデータセットをスキャンする BE が少ない物理セグメント Split 数、利用可能な BE、スキャナーのスケジューリングより均衡したセグメントを比較する。パイプラインインスタンスを増やすだけではセグメントを分割できない
セグメントを増やすと CPU、メモリ、マージ時間が増えるSplit あたりの候補数、top_k + offset、クエリ同時実行数セグメント数を減らす、またはアプリケーションが必要とする以上の候補を要求しない。検索設定を変更した場合は再現率を再確認する
キャッシュヒット率は高いがレイテンシーが高いスコアリング、Prefilter 処理、デコード、二段階目の取得時間支配的な段階を最適化する。インデックスキャッシュを増やしても計算や取得はなくならない
メタデータの再ロードが続くメタデータキャッシュの使用量とヒット/ミス差分、Fragment/ファイル数、バージョン変更再利用とメモリが許せば lance_metadata_cache_size_bytes を独立して調整する
キャッシュ使用量が容量未満なのにプロセスメモリが高い同時実行クエリのアロケーション、アクティブなロード、保持されるオブジェクト、他の BE ワークロード測定したピークに基づいて同時実行数またはキャッシュ予算を下げる。キャッシュ容量はプロセスメモリの上限ではない
データファイル I/O が高いままディスクキャッシュのカウンター、再利用、読み取りブロックサイズ、クエリ出力列データキャッシュの予算または読み取り粒度を調整する。インデックスファイルはこのディスクデータキャッシュを使用しない

Query Profile referenceを使用して、FE のメタデータ/計画、BE のインデックス/スキャン処理、二段階目の行 ID 取得を分離します。キャッシュカウンターと BE 全体のメトリクスについては、Checking Cache Effectivenessを使用してください。集計されたヒット率だけでは、どのインデックスが追い出されたか、どの段階がレイテンシーを支配しているかは特定できません。設定は一度に 1 つだけ変更し、各比較についてワークロード、インデックスバージョン、BE 配置、レイテンシー、スループット、再現率、ピークメモリを記録してください。