Milvus 外部コレクション:データを移動せずにデータレイク内のデータをインデックス化して検索する
多くのAIパイプラインでは、エンベディングとメタデータはすでに生成され、データレイクに保存されています。プロダクトパイプラインは、製品属性とマルチモーダルエンベディングをS3のParquetファイルに書き込むことがあります。検索用コーパスやトレーニング用コーパスは、IcebergテーブルやLanceテーブルに存在することがあります。レイクは、これらのデータセットが生成・更新・バージョン管理され、他のデータスタックによって使用される場所です。
しかし、ベクターデータベースは伝統的に、データベースが所有するサービングコピーを中心に構築されてきました。チームがすでにレイクにあるデータに対して低遅延のベクター検索を行いたい場合、一般的に2つの選択肢がありました:
- データをベクターデータベースにコピーする。これによりANNインデックスと本番サービングパスが提供されますが、データセットの2番目のコピーと、ソースと同期を保つ必要があるETLパイプラインが作成されます。
- レイクを直接クエリする。これにより重複は回避されますが、ANNインデックスとサービングレイヤーがないため、ベクター検索は本番レイテンシー向けに設計されていないスキャンにフォールバックします。
Milvus 3.0 外部コレクション は3つ目の道を導入します。ソースデータはParquet、Iceberg、Lance、Vortex、その他のサポートされている外部形式に残り、Milvusはその上にインデックスを構築して提供します。外部フィールドをMilvusスキーマにマッピングし、必要なインデックスを定義し、コレクションをリフレッシュして、通常のMilvus検索・クエリAPIを使用します—ソース行を先にMilvus管理コレクションにコピーする必要はありません。
アーキテクチャの変更はシンプルです:データはレイクに残り、Milvusがインデックスと検索レイヤーを追加します。
これにより、外部コレクションは、ベクターレイクベース(Vector Lakebase)への重要な一歩となります。これは、オープンレイクストレージ、再利用可能なレイクレベルのインデックス、共有セマンティックレイヤーとベクターデータベースレベルのサービングを組み合わせた、AIのための統合的でレイクネイティブなデータアーキテクチャです。オンライン検索は、Spark、トレーニングパイプライン、評価ジョブ、ガバナンスツールが別のバージョンのデータで動作している間、別のサービングコピーから始める必要がなくなります。それらは同じレイク常駐データ基盤から作業できます。
外部コレクションとは何か、そしてそれが何を変えるのか
外部コレクションは、ソースデータがMilvus管理ストレージの外部に存在するMilvusコレクションの一種です。
外部コレクションがない場合、そのカタログを本番ベクター検索の背後に置くことは、通常Milvusに別のコピーを作成することを意味します:
カタログが変更されるたび、エンベディングモデルが変更されるたび、またはフィールドがバックフィルされるたびに、別のパイプラインが更新されたデータをその境界を越えて移動させる必要があります。
外部コレクションを使用すると、アーキテクチャは次のようになります:
Milvusは外部ファイルを独自のソースデータコピーにしません。代わりに、外部コレクションにはMilvusがそれらを解釈して検索するために必要な情報が含まれています:
- 外部ファイルまたはテーブルを識別する
external_source。 - ソース形式とストレージアクセスを記述する
external_spec。 - Milvusスキーマのフィールドを外部データセットの列に接続する
external_fieldマッピング。 - Milvusが検索用に作成するインデックス、マニフェスト、サービング状態。
ゼロコピーのソースデータは、Milvus内部の状態がゼロであることを意味しません。Milvusは依然としてインデックスを構築します。依然としてコンピュートを使用します。依然としてデータをキャッシュします。変更点は、Milvusで検索する必要があるからといって、信頼できるソースの行をMilvusにコピーする必要がなくなったことです。
通常のMilvusコレクションと外部コレクション
| 関心事 | Milvus管理コレクション | 外部コレクション |
|---|---|---|
| ソースレコード | Milvusによって保存・管理される | 外部ファイルまたはテーブルに残る |
| Milvusへのデータの入り方 | 挿入、アップサート、インポート、またはストリーミング書き込み | 外部ソースマッピング + リフレッシュ |
| オンライン変更 | サポートあり | Milvusからは読み取り専用 |
| 鮮度 | Milvusの書き込みパスと整合性モデルに従う | 最後に正常に公開されたリフレッシュに従う |
| Milvus管理状態 | ソースデータ、メタデータ、インデックス、キャッシュ | マッピング、マニフェスト、インデックス、キャッシュ |
| クエリパス | Milvusの検索およびクエリAPI | Milvusの検索およびクエリAPI |
| 最適な用途 | 継続的に変化するオンラインデータ | 大規模でバッチ生成され、読み取りが多いレイクデータ |
したがって、外部コレクションは通常のMilvusコレクションを置き換えるのではなく、補完します。
システムは、通常のMilvusコレクションで急速に変化するオンライン状態を保持しながら、大規模なコーパス、カタログ、履歴データセット、モデル特徴量、またはレイク内で既に生成・管理されているその他のデータに外部コレクションを使用できます。
2番目のコピーを削除することが重要な理由
外部コレクションをストレージ最適化として説明したくなります:数テラバイトのデータを別のデータベースにコピーしないことで、ストレージを節約できます。これは有用ですが、主要なアーキテクチャ上の問題ではありません。
より高いコストは、2つのデータシステムを整合させ続けることから生じます。
もう一度製品カタログを考えてみましょう。データプラットフォームが信頼できるParquetデータセットを生成します。検索機能がそれをベクターデータベースにインポートします。レコメンデーションチームはSparkを通じて同じレイクデータをオフライン分析用に読み取るかもしれません。その後、新しいエンベディングモデルが置換用のベクター列を生成します。在庫とメタデータは同時に変化し続けます。
オンラインサービングコピーがレイクから独立すると、すべての変更がその境界を越える必要があります:
- データをコピーする必要があります;
- 転送をスケジュールして監視する必要があります;
- 失敗したジョブには再試行が必要です;
- スキーマと権限を複数のシステムで表現する必要があるかもしれません;
- 鮮度は同期パイプラインが追いつく速さに依存します;
- チームはどのコピーが実際に必要なバージョンを表しているかを把握する必要があります。
ストレージは単なる1つの項目にすぎません。
| コスト | 分離されたレイク + サービングコピー | 外部コレクション |
|---|---|---|
| ソースデータのコピー | レイクコピーに加えて別のサービングコピー | ソース行はレイクに残る |
| データ移動 | 持続的なETL/インポートパイプライン | 外部ソースに対するリフレッシュ |
| 鮮度 | エクスポート/インポートの頻度に依存 | 新しいリフレッシュが公開されるタイミングで制御 |
| ガバナンス | ソースコピーとサービングコピーを整合させ続ける必要がある | ソースの所有権、系統、バージョン管理はレイクプラットフォームに残る |
| オフライン再利用 | 他のコンシューマーが独自のコピーを準備する可能性がある | 既存のレイクツールが同じソースを読み続けることができる |
| サービングリソース | データベースコピーとクエリワークロードに基づいてサイズ設定 | インデックス作成、クエリコンピュート、キャッシュをソース行の所有権から分離して管理できる |
この違いは、AIデータの変更がより頻繁になるにつれて特に重要になります。
チームはコーパスの重複を排除します。分析のためにデータをクラスタリングします。モデルが変更されると新しいエンベディングを生成します。ラベル、要約、抽出されたエンティティ、品質スコア、フィードバックシグナルを追加します。本番アプリケーションが検索するのと同じコーパスに対して評価ジョブとデータクリーニングパイプラインを実行します。
すべてのシステムが独自のコピーを所有している場合、すべての改善が別の同期ジョブになります。
外部コレクションはその境界を変えます:オフラインシステムはレイクデータセットで作業を続けられ、Milvusは同じ基盤上で検索を提供します。
外部コレクションがサポートするデータソース
外部コレクションは、Milvus固有のソースレイアウトではなく、オープンで外部管理されたデータを中心に設計されています。Storage V3を通じて複数の外部ソース形式をサポートしています:
| 外部形式 | format値 | Milvusが読み取るもの |
|---|---|---|
| Apache Parquet | parquet | Parquetファイルと行グループを含むディレクトリまたはオブジェクトストレージプレフィックス |
| Vortex | vortex | Vortexファイルとそのレイアウトメタデータ |
| Lance | lance-table | Lanceデータセットとそのフラグメントメタデータ |
| Apache Iceberg | iceberg-table | Icebergメタデータと選択されたスナップショット |
| Milvusスナップショット | milvus-table | 外部ソースとして公開されたサポートされているMilvusスナップショット |
ソースとMilvusの間のマッピングは明示的です。
product_idという名前のソース列はMilvusフィールドidになります;image_vecはembeddingになります;そして幅広いソーステーブルはすべての列をコレクションに公開する必要はありません。つまり、データプラットフォームはサービングデータベースを満たすためだけにソースをリネームしたり書き換えたりする必要はありません。
バージョン管理された形式はもう1つの有用な特性を追加します。Icebergなどのソースを使用すると、コレクションはクエリ実行時に現在のものではなく、特定のスナップショットを指すことができます。固定されたソースバージョンは、再現可能な評価、回帰テスト、履歴分析、監査ワークロードに役立ちます。
基盤となるファイルは、他のデータスタックでも引き続き使用できます。Spark、トレーニングフレームワーク、ガバナンスシステム、その他のレイク互換ツールは、同じオープンデータを読み続けることができます。
外部コレクションはそのデータの別のコンシューマーを追加します;Milvusを唯一の所有者にするわけではありません。
外部ストレージへの安全なアクセス
Milvusは外部ストレージを読み取るための権限も必要とします。
ストレージプロバイダーに応じて、デプロイメントではアプリケーション設定に長期有効な認証情報を埋め込む代わりに、ワークロードIDやインスタンスID、AWS STSロール引き受け、サービスアカウントのインパーソネーション、SASベースのアクセス、プロバイダー固有のロールシステムなどのメカニズムを使用できます。
このストレージIDはMilvusがソースに到達する方法を制御します。Milvus内部の認可は別のセキュリティ境界として残ります。
外部コレクションの作成、インデックス作成、リフレッシュ、クエリ方法
外部コレクションのライフサイクルには4つの主要なステップがあります:
- 外部ソースを定義し、その列をMilvusスキーマにマッピングします。
- ワークロードに必要なインデックスを定義します。
- Milvusがソースデータを発見してクエリ可能なバージョンを準備できるようにリフレッシュを実行します。
- コレクションをロードして通常のMilvus検索およびクエリAPIを使用します。
同じ製品カタログを外部コレクションとして表現した例です:
import json
import time
from pymilvus import DataType, MilvusClient
client = MilvusClient(
uri=“http://localhost:19530”,
token=“root:Milvus”,
)
schema = client.create_schema(
external_source=“s3://my-lake/datasets/products/”,
external_spec=json.dumps(
{
“format”: “parquet”,
“extfs”: {
“cloud_provider”: “aws”,
“region”: “us-east-1”,
“use_iam”: “true”,
“iam_endpoint”: “https://sts.us-east-1.amazonaws.com”,
},
}
),
)
schema.add_field(
field_name=“id”,
datatype=DataType.INT64,
external_field=“product_id”,
)
schema.add_field(
field_name=“embedding”,
datatype=DataType.FLOAT_VECTOR,
dim=768,
external_field=“image_vec”,
)
schema.add_field(
field_name=“title”,
datatype=DataType.VARCHAR,
max_length=256,
external_field=“product_name”,
)
schema.add_field(
field_name=“stock”,
datatype=DataType.INT64,
external_field=“stock”,
)
schema.add_field(
field_name=“rating”,
datatype=DataType.FLOAT,
external_field=“rating”,
)
client.create_collection(
collection_name=“products_ext”,
schema=schema,
)
インデックスは通常のMilvusインターフェースを使用します:
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="HNSW",
metric_type="COSINE",
)
index_params.add_index(field_name="stock", index_type="AUTOINDEX")
index_params.add_index(field_name="rating", index_type="AUTOINDEX")
client.create_index(
collection_name=“products_ext”,
index_params=index_params,
)
次に外部ソースをリフレッシュします:
job_id = client.refresh_external_collection(
collection_name="products_ext",
)
while True:
progress = client.get_refresh_external_collection_progress(job_id=job_id)
if progress.state == “RefreshCompleted”:
break
if progress.state == “RefreshFailed”:
raise RuntimeError(progress.reason)
time.sleep(2)
リフレッシュされたバージョンが準備できたら、通常のMilvusコレクションと同様にロードして検索します:
client.load_collection("products_ext")
results = client.search(
collection_name=“products_ext”,
data=[query_vec],
anns_field=“embedding”,
filter=“stock > 0 and rating >= 4.0”,
limit=10,
output_fields=[“id”, “title”, “stock”, “rating”],
)
重要な違いは検索呼び出しではありません。ライフサイクルがどこから始まるかです。Milvus管理コレクションは、データがMilvusに書き込まれるかインポートされるところから始まります。外部コレクションは、すでに他の場所に存在するデータへの参照から始まります。
リフレッシュが外部データの変更をどのように取得するか
外部コレクションはMilvus側からは読み取り専用ですが、基盤となるレイクデータセットは永遠に凍結されている必要はありません。
製品パイプラインが別のバッチを追加したり、メタデータを更新したり、新しいモデルからエンベディングを書き込んだりするとします。Milvusはソースパスに現れるすべてのオブジェクトを継続的に追跡するわけではありません。これらの変更はリフレッシュを通じて可視化されます。
リフレッシュは外部メタデータを読み取り、ソースフラグメントを解決し、それらをMilvusコレクションに接続するマニフェストを更新し、対応するインデックス状態を準備します。
重要なのは、この作業が増分で実行できることです。
Milvusは変更されていないソースフラグメントを識別し、既存のセグメントとインデックスの作業を再利用できます。新規または変更されたフラグメントは、新しい処理を必要とする部分です。
したがって、複数テラバイトのデータセットへの小さな変更でも、別の完全インポートと完全なインデックス再構築をトリガーする必要はありません。
リフレッシュはサービングシステムに明確なバージョン境界も提供します。新しいバージョンが準備されている間、クエリは以前に公開された状態を引き続き使用します。リフレッシュが完了すると、新しい状態は古いデータと部分的に準備されたデータの混合を公開するのではなく、完全なバージョンとして利用可能になります。
このモデルは、時間ごとのカタログ構築、夜間のナレッジベース更新、定期的なエンベディングリフレッシュ、モデル生成の特徴量パイプライン、および同様のバッチ指向ワークロードに自然に適合します。
これはストリーミング書き込みパスを置き換えるものではありません。すべての挿入や削除がMilvusを通じて即座に検索可能になる必要がある場合、管理コレクションの方が優れたモデルです。
遅延ロードが幅広いデータセットのメモリ使用量をどのように削減するか
ソース行をオブジェクトストレージに保持しておくことは、サービングレイヤーがクエリに応答する前にすべてのバイトをローカルにロードする必要がない場合にのみ役立ちます。Milvus階層型ストレージを有効にすると、その必要はありません。
コレクションのロード時に、クエリノードは最初はスキーマ情報、インデックス定義、チャンクマップ、リモートオブジェクトへの参照などの軽量なメタデータのみを保持できます。フィールドデータはクエリが必要としたときにチャンクレベルでフェッチされます;インデックスは最初の使用までリモートに保持され、その後ローカルにキャッシュされます。頻繁に使用されるデータはホットな状態を維持し、アクセス頻度の低いデータは退避できます。
これは特に幅広いAIデータセットに役立ちます。
製品行には、複数のエンベディング、長い説明、生のJSON、画像メタデータ、生成された要約、在庫、価格、評価、その他多くの属性が含まれる可能性があります。典型的な類似性検索では、1つのベクターに加えて在庫、価格、評価のみにアクセスする場合があります。同じレコードに属しているというだけの理由で、他のすべてのフィールドが永続的にサービングメモリを占有する必要はありません。
外部コレクションは、サービングフットプリントを2つのレベルで狭めることができます:
- まず、スキーマレベルの射影。
external_fieldを通じて、外部コレクションはアプリケーションが必要とするソース列のみを公開できます。他の列はレイクデータセットに残り、このサービングスキーマには含まれません。 - 次に、ランタイム射影。階層型サービングモデルでは、クエリノードはマッピングされたデータセット全体を事前にロードするのではなく、ワークロードに実際に必要なフィールドとインデックスをフェッチしてキャッシュします。
言い換えると、データセットはレイク内で幅広いままでありながら、サービングフットプリントを同じように幅広くする必要はありません。
明らかなトレードオフがあります。コールドフィールドやインデックスにヒットするクエリは、最初のアクセス時にリモート読み取りコストを支払う可能性があります。ウォームアップポリシーはレイテンシーに重要なフィールドやインデックスを事前ロードでき、キャッシュと退避ポリシーはアクセス頻度の低い状態がローカルリソースを無期限に占有しないようにします。
ポイントは、オブジェクトストレージがRAMのように動作するということではありません。メモリとローカルディスクが、ソースデータセットの総サイズと幅ではなく、検索ワークロードのワーキングセットに追従できるということです。
ソース形式もここでは重要です。広範な分析スキャン用に設計された形式と、より狭いまたはランダムな読み取り用に最適化された形式では、オンデマンドアクセス時に異なるI/O動作が発生する可能性があります。外部コレクションはこれらのストレージレベルのトレードオフを消し去るわけではありません;その上にMilvusが検索レイヤーを構築できるようにします。
外部コレクションがサポートする検索およびインデックス機能
外部コレクションは、単にMilvusをエンベディングのディレクトリに向けてファイルをスキャンするものではありません。Milvusは外部データ上に検索構造を構築し、標準の検索エンジンを通じてクエリを実行します。
外部データ上に構築されるMilvusインデックス
フィールドとワークロードに応じて、Milvusは以下を構築できます:
- ANN検索用のベクターインデックス;
- メタデータフィルタリング用のスカラーインデックス;
- 半構造化属性用のJSONインデックス;
- 語彙検索用のBM25および全文インデックス。
- Milvusデータモデルでサポートされている関数生成フィールド。
ANN検索はこれらのインデックスを使用して、すべてのソースベクターを読み取る代わりに候補セットを絞り込みます。
この違いは重要です。なぜなら、レイクにエンベディングを保存することは、その上でベクターデータベースを運用することとは異なるからです。永続化はバイトを提供します。本番検索には、インデックス、クエリプランニング、フィルタリング、ランキング、キャッシュ、低遅延のサービングパスも必要です。
ベクターtop-Kを超えて
もう1つの一般的な誤解は、「外部コレクション」を「Parquet上のベクター検索」と読むことです。それは本番検索が実際に必要とするものを過小評価しています。
本番の検索結果がベクター類似度だけに依存することはほとんどありません。正確な用語、アクセスポリシー、在庫、タイムスタンプ、カテゴリ、価格、ソース品質、ビジネスランキングシグナルにも依存する場合があります。
次のようなクエリを考えてみましょう:
| 夏用の赤い花柄ドレス、在庫あり、評価の高い順 |
|---|
本番の検索パスには複数のシグナルが必要になる場合があります:
- ベクター類似度:「夏用の花柄ドレス」の意味的類似性を捉えます。
- 語彙検索または全文検索:「赤」などの正確な用語を検索します。
- スカラーフィルター:在庫切れまたは評価しきい値以下の製品を除外します。
- ハイブリッド検索とランキング:複数の検索シグナルを組み合わせます。
Milvus 3.0はまた、サーバーサイドの順序付け、集約、ファセットなどの機能により、クエリエンジンを初期の最近傍検索を超えて拡張します。
より広いポイントは、外部コレクションがレイク常駐データにデータベースの検索パスを提供するということです—単にファイルからベクターを読み取る方法ではありません。
同じレイクデータがオンラインサービングとオフライン処理をどのようにサポートするか
ソースをオープンレイク形式で維持する最も強いアーキテクチャ上の理由は、単に2番目のコピーにコストがかかるからではありません。それは、同じデータセットが継続的に改善するシステムに対して利用可能なままであることができるからです。
製品カタログに戻りましょう。
日中、Milvusは製品検索、レコメンデーション、またはエージェント検索のために外部コレクションを提供できます。
同時に、他のシステムはレイクデータセット上で直接作業できます:
- Sparkは重複する製品を識別できます。
- トレーニングパイプラインは新しいモデルからエンベディングを生成できます。
- データ品質ジョブは不正な形式や異常なレコードを検出できます。
- 評価パイプラインはモデルバージョン間の検索品質を比較できます。
- バッチプロセスは要約、ラベル、追加のメタデータを生成できます。
外部コレクションはこれらのジョブを自分で実行するわけではありません。SparkはSparkのままです;トレーニングはトレーニングのままです。その役割は、それらの間の余分なサービングデータ境界を削除することです。
オフライン作業は改善されたデータや新しいフィールドをレイクに書き戻すことができます。後続のリフレッシュにより、更新されたソースがMilvus検索パスで利用可能になります。
サービング用に別の信頼できるコピーを再構築することだけを目的とした、別のエクスポートとインポートのループはありません。
ガバナンスも明確に分割されたままです。ソースバージョン、系統、ソースの所有権はレイクプラットフォームに残ります。Milvusは独自のコレクションレベルの認可と、ソースを読み取るために必要な認証情報を維持します。単一のデータ基盤を共有することは、すべてのセキュリティドメインを単一のシステムに統合することを意味しません。
これがベクターレイクベースとの関連です:レイクは共有データ基盤のままであり、Milvusはその上に低遅延の検索レイヤーを提供します。外部コレクションは、Storage V3、スナップショット、Spark統合、スキーマ進化、バックフィルと並んで、そのアーキテクチャの一部です。
外部コレクションが適している場所—そして適していない場所
外部コレクションは以下の場合に最適です:
- 信頼できるデータがすでにParquet、Vortex、Lance、Iceberg、その他のサポートされている外部ソースに存在する場合。
- データセットが主にバッチで生成され、高頻度のトランザクション書き込みではない場合。
- 2番目のサービングコピーの維持に大きなETL、鮮度、またはガバナンスのオーバーヘッドが発生する場合。
- 複数のシステムが同じオープンデータセットで作業する必要がある場合。
- サービングの鮮度に対して明示的なリフレッシュ境界が許容できる場合。
- Milvusをソース行の所有者にせずに本番のMilvus検索を実現したい場合。
通常のMilvusコレクションが依然としてより良い選択となるのは以下の場合です:
- アプリケーションがレコードを継続的に挿入またはアップサートする場合;
- 削除がオンライン書き込みパスを通じて可視化される必要がある場合;
- ワークロードが外部スキーマでは利用できないコレクション機能に依存する場合;
- サービング設計が意図的に必要なデータをすべてメモリに保持し、リモートキャッシュミスを回避する場合。
いくつかの境界を覚えておく価値があります。
- 外部コレクションは読み取り専用です。ソースの変更はMilvusの外部で行われます。
- ゼロコピーはソース行に適用されます。インデックス、マニフェスト、キャッシュ、コンピュートは依然としてリソースを消費します。
- リフレッシュは明示的です。ストリーミング同期メカニズムではありません。
- ソースは到達可能な状態を維持する必要があります。検索、インデックス、リフレッシュの動作はストレージアクセスと認証情報に依存します。
- Storage V3が必要です。オープンソースのMilvus 3.0では、外部コレクションを使用する前に有効化する必要があります。
- 外部コレクションは上流の処理を置き換えません。エンベディング生成、クラスタリング、重複排除、データクリーニングは適切な上流システムで引き続き行われます。
したがって、この選択は二元的ではなく補完的です。システムは、急速に変化するオンライン状態には通常のMilvusコレクションを、自然な居場所がレイクである大規模なバッチ生成データセットには外部コレクションを使用できます。
Milvus 3.0で外部コレクションを試す
外部コレクションはMilvus 3.0で利用できます。代表的なレイクデータセットから始めて、ワークロードにとって重要な側面を評価してください:初期および増分リフレッシュ、インデックス構築コスト、ウォームおよびコールドクエリの動作、アプリケーションが必要とする鮮度間隔。
実装の詳細については、以下を参照してください:
マネージドパスを希望する場合、外部コレクションはZilliz CloudのZilliz Vector Lakebaseの一部としても利用できます。以下を参照してください:
実装に関する質問やフィードバックは、Milvus GitHubリポジトリまたはMilvus Discordコミュニティにお寄せいただくこともできます。
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



