🔡

(日本語訳) Vector databases (Part 4): Analyzing the trade-offs

2023/09/28に公開
1

日本語訳: ベクトルデータベース(パート4): トレードオフの分析

訳者前書き

ベクトルデータベースについていろいろと調査・検証していたところ、以下の記事を見つけて、内容が非常によくまとまっており、多くの人にとっても有用な記事ではないか感じました。もはや翻訳などはDeepLやChatGPTで簡単にできる時代になりつつありますが、まだまだ検索エンジンで検索されることも多いと思いますし、少しでも参照しやすくなればと考えて、作者であるPrashanth Rao氏に許可を頂いた上で日本語に翻訳したものとなっています。

全4回の記事の第4回目となります。

元記事
https://thedataquarry.com/posts/vector-db-4/

Prashanth Rao氏のGitHubアカウント
https://github.com/prrao87

Prashanth Rao氏のTwitterアカウント
https://twitter.com/tech_optimist

前回の日本語訳はこちら

https://zenn.dev/kun432/articles/20230921-vector-databases-jp-part-3


ユースケースに適したベクトルDBソリューションの選択

おかえりなさい!このシリーズの前回の投稿では、ベクトルDBで一般的に使用されるさまざまなタイプのインデックスについて検討した。しかし、ベクトルデータベースにおいて、インデックス作成は大きな問題の一ほんの一部に過ぎない。第2回では、ベクトルデータベースとは何かを説明した。世の中にある様々なベクトルDBを区別するためには、以下のコンポーネントの関係を理解する必要がある:

  • アプリケーションレイヤーとその位置
  • データレイヤーと、データベースやアプリケーションレイヤーとの位置関係
  • インデックス作成戦略と、メモリおよびCPU使用量との関係
  • ストレージレイヤーの設計
  • これら全ての側面に関連するスケーラビリティとコストの検討

これらのコンポーネントは、それぞれに固有のトレードオフを伴う。私はこれを以下の通りにカテゴライズしてみた ー もちろん見落としている点もあると思うが、出だしとしては良いだろう。🤓 それではさっそく本題に入ろう。

1. オンプレミス vs とクラウドホスティング

多くのベンダーは、「クラウドネイティブ」機能を、拡張性の観点から「食パンがスライスされて売られるようになった」ことと同じくらいの画期的なものとして強調している。しかし、コストの観点から最適なソリューションを決めるには、そもそもホスティングの選択肢がどのように分かれているかを考えることが重要だ。組み込みデータベースアーキテクチャも、もはや選択肢の一部なのである!🎉

次の組み合わせを考えてみよう:

  • クラウドネイティブ(マネージド)+クライアント/サーバ
  • オンプレミス(セルフホスト)+組み込み
  • クラウドネイティブ(マネージド)+組み込み

これらの組み合わせを視覚的に比較するとよりわかりやすい。

最も一般的なデータベースアーキテクチャーはクライアント/サーバ型アーキテクチャであることは明白であり、それは長年にわたって他の様々なデータベースによって試されてきたためである。組み込み型/サーバーレスホスティングモデルは、以下に述べる理由により特に興味深い。

クライアント・サーバー・アーキテクチャと組み込みアーキテクチャ

DuckDBがMotherDuck[1]を通じてオープンソースの組み込みSQL DBを収益化したことは、他の新興データベースベンダーにとってのインスピレーションとなっている。ベクトルの世界では、この点でひときわ目立つベンダーがある:LanceDB[2]だ。LanceDBは比較的新しいベンダーで、組み込み型のサーバーレス設計を採用しており、そのオープンソース版はすぐに使えてかつ最初からスケーラブルになっている。


lancedb.com

もう1つの有名なデータベースであるChromaも組み込み型オプションを提供しているが、純粋なインメモリデータベースであり、単一のマシン上で動作するため、クラウド上でホストされる従来のクライアント/サーバ型モデルへの移行を進めているように思われる[3]。MilvusのサーバレスバージョンをラップしたZilliz[4]も、クラウド上の無料版で組み込みDBを提供している。しかし、デフォルトで組み込み型として構築されているのはLanceDBだけである。

オンプレミスとクラウドストレージにまたがって多くのデータを保持する組織にとって、組み込み型/サーバレスのベクトルDBは、データレイヤーをアプリケーションレイヤー(ユーザーがデータを操作する場所)を接続する際、特にプライバシーとセキュリティが懸念される場合には、開発者に大きな自由度と柔軟性を提供する。

多くのベンダーが、仮想プライベートクラウド(VPC)内にセキュアなエンドポイントを配置したフルマネージド型のクラウドホストソリューションを提供しているにもかかわらず、企業はすべてのデータとベクトル計算をクラウドに移行することに躊躇することがある。これは、機密性の高いデータを抱え、クラウドネイティブではないレガシーシステムとのインターフェースを必要とする大企業の場合、特に当てはまる。このような場合、LanceDBのような組み込み型ベクトルデータベースをオンプレミスに導入し、アプリケーションレイヤーに接続する方が簡単な場合が多い。

コスト

クラウドネイティブのマネージドソリューションを提供するデータベースは通常、保存されたデータ量とそれに対するクエリの回数に基づいて課金する。これは、多くのデータを持っているが、それを転送・保存するためのインフラにお金を払いたくないという組織には最適なモデルだ。しかし、多くのデータを持っているが、すでに社内にデータインフラチームがあり、オンプレミスまたは組み込みホスティングをサポートできる体制を整えている企業にとっては、インデックス作成とクエリの両方のためにデータをクラウドに送ることは、ほとんど意味をなさない。

組織の規模がいつ「臨界質量」に達したかを定義するのは難しいが、我々が長年慣れ親しんできたクラウド上に展開される標準的なクライアント/サーバ型データベースアーキテクチャが、2023年には唯一の選択肢ではないことを知っておくことは重要だ。

検討すべきポイント:

  • 私のデータセットは、クラウド上で、オンデマンドで、弾力的に、拡張する必要があるほど急速に成長しているか?
  • オンプレミス/組み込みホスティングをサポートするのに十分な確立されたデータインフラチームを持っているか?
  • 私のデータセットは、オンプレミスに置かないといけないほど機密性が高いのか?
  • フルマネージドのクラウドホスティングソリューションの場合、クエリごとや保存データ1GBごとに支払うコストはどうなるのか?

2.専用ベンダー vs 既存ベンダー

多くの組織はすでに既存のソリューション(Elasticsearch、Meilisearch、MongoDBなど)に投資している。これらのソリューションはベクトル検索専用に作られたものではないが、既存のソリューションの上にベクトル検索機能を追加している。もし、既存のアプリケーションにベクトル/セマンティック検索機能を追加しようとしているのであれば、まずは既存のデータベースのベクトル検索機能を試してから、これらのソリューションのコスト的な影響を検討した上で、外部のオプションに目を向けるのは理にかなっている。

しかし、既存のベンダーが提供するベクトル検索機能には、いくつかの注意点がある。例えば、Elasticsearchは、ベクトル検索の提供を利用できるクライアントの種類に多くの追加的な制約があり、そのツール一式を利用するためには特別なデプロイやライセンス条件が必要となることがある。MongoDBは、彼らが提供しているAtlasクラウド環境でのみベクトル検索を提供しており、セルフホストの場合は提供していない。これらは重要な検討事項である!

重要な点として心に留めておくべきことは、Qdrant、Weaviate、LanceDBなどのベクトル専用DBベンダーをはじめとする多くの企業は、ベクトル検索のためのストレージ、インデックス作成、およびクエリ戦略の最適化に数千時間を費やしてきたということだ。また、彼らはGoやRustのようなモダンなプログラミング言語を使用して、システムをフルスクラッチから構築してきたことにより、大規模なスケーラビリティと高い性能を持つように設計されているという利点がある。専用ベクトルデータベースソリューションのほとんどすべてはPythonやJavascriptのクライアントを提供しており、自分のデータでテストしてより適切な決定を下すための情報を得るのも容易である。

検討すべきポイント:

  • ベクトル検索に使用できる既存のデータベースをすでに持っているか?
  • 既存のソリューションと専用ソリューションのパフォーマンスを比較するために、自分のデータで簡単なベンチマークを実行できるか?
  • そのソリューションはデータの増加に合わせてスケールするか?

多くの場合、ベクトル検索を追加した既存のソリューションは、ベクトル専用データベースほどの性能を発揮しないのが現実である。これは、pgvector/PostgreSQLとQdrantを比較したベンチマーク調査[5]で非常に明確に示されている ー ネタバレ: pgvectorは、どの指標においてもQdrantよりもずっと遅く、内部での最適化もはるかに少ない。

3.追加速度とクエリ速度

Milvus/Zillizのような既に実績のある一部のベンダーは、ベクトルが必要とされる大規模なストリーミングのユースケースを検討している。ビデオ監視や金融取引の追跡のようなリアルタイムのシナリオでは、毎分数千のベクトルを追加しインデックスを作成することが不可欠であり、Milvus/Zillizはこの問題に全力で取り組むことが可能だ。[6]

しかし、追加速度は大半のユースケースにとって本当に重要なのだろうか?多くの組織にとっては、クエリ速度の方がより重要である。というのも、追加やインデックス作成は通常あまり頻繁に行わるものではなく、データのクエリが遥かに頻繁に行われる上、その場合はユーザーインターフェースを通じたリアルタイムレベルであるのが一般的だからである。Rust🦀で書かれたオープンソースのベクトル専用データベースであるQdrantは、まさにこのユースケースのために最適化されている。Rustで書かれているため、インデックス作成も非常に高速に動作するが、Qdrantのドキュメントのデモで示されているリアルタイム入力セマンティック検索のような、わずか数ミリ秒で最適な結果を返すベクトル検索ソリューションを、実際の環境でも実現できるのである。🤯

https://twitter.com/qdrant_engine/status/1691054852913418241

検討すべきポイント:

  • どれくらいの頻度で大量のベクトルを挿入(およびインデックス作成)することになるか?
  • クエリ時にアプリケーションのレイテンシ要件を満たしているか?

4.再現率 vs レイテンシ

再現率はクエリによって返される関連結果の割合であり、レイテンシは結果を返すまでの時間である。リコールとレイテンシの最適化に関しては、データベースベンダーによってトレードオフの関係が異なっている。

このシリーズの第3回でのまとめ:

  • Flat インデックスは、ベクトルを変更されていない形式で保存し、正確なkNN検索に使用される。最も正確で、同時に最も遅い
  • IVF-Flat インデックスは、検索空間を迅速に絞り込むために転置ファイルインデックスを使用し、総当たり検索よりもはるかに高速ですが、再現率の形でいくらかの精度を犠牲にしている
  • IVF-PQ は、ベクトルを圧縮するためにIVFと直積量子化を組み合わせて使用することで、メモリ使用を削減し、検索を高速化する。純粋な PQ インデックスよりも再現率に優れている
  • HNSW は、圧倒的に最も人気のあるインデックスであり、HNSW-PQ の形で直積量子化と組み合わせて使用されることが多く、IVF-PQ と比較して検索速度とメモリ効率が向上している
  • Vamana は、オンディスクのパフォーマンスに特化して設計・最適化された比較的新しいインデックス。メモリよりも大きなベクトルデータを保存しつつ、HNSW 同様の速度を公約としている
    • しかし、まだ始まったばかり、かつ、オンディスクのパフォーマンスというチャレンジングな課題のため、多くのデータベースはまだ実装する方向には進んでいない

これらのトレードオフを念頭に置きながら、このシリーズの以前のイメージを参照してほしい。

IVF-PQは、完璧な関連性がアプリケーションの成功において不可欠でない、初期段階のユースケースやPOCには適している。しかし、より高い品質と関連性を求める場合、専用ベンダーのほとんどはHNSWインデックスを使用している。近年、WeaviateやQdrantのようなベンダーは、非常に大きなデータセットのメモリ効率を向上させるために、HNSWと直積量子化(PQ)を組み合わせて使用し始めている。

検討すべきポイント:

  • 自分のユースケースにおいて、検索の再現性の重要度はどれくらいか?
    • 一般的に、自分のデータを用いたクエリに関するベンチマーク調査が、この問いに答えるのに役立つ。
  • 自分のユースケースにおいて、レイテンシの重要度はどれくらいか?
    • データセットが非常に大きい場合、メモリ消費を減らすために、IVF-PQやHNSW-PQのような直積量子化インデックスを使用することは理にかなっているかもしれない。

5. インデックスとベクトルストレージにおける、インメモリ vs オンディスク

Redisのようなデータベースは完全にインメモリで、非常に高速である。しかし、ユースケースによってはメモリよりも大きなベクトルを保持しないといけない可能性が高い。ANN検索速度も維持しつつ、非常に大きなデータ(数億、あるいは数十億のベクトル)に対してベクトルストレージをスケールさせるには、いくつかの工夫を組み合わせる必要がある。QdrantやWeaviateのようなデータベースは、ディスク上のページキャッシュの仮想アドレス空間を利用する、ベクトル用メモリマップファイルのオプションを提供しており、RAMへの全データの読み込みを回避できる。これにより、実際にデータをディスク上に永続化することなく、インメモリデータベースの速度をほぼ維持できる。

インデックスの観点から見ると、HNSWは最もメモリを多く消費することで知られており、ベクトルデータセットが大きくなるにつれて、メモリ外インデックスに対してどの程度スケールするのかという自然な疑問が生じる。前項で説明したように、PQとHNSWを組み合わせることで、必要なメモリを減少させることができる。比較的新しいインデックスであるVamanaは、DiskANNアルゴリズムの一部であり、最も有望な方法の1つとされている(現在はLanceDB[7]とMilvus[8]のみで利用可能)。そして、それは、HNSWと同等の性能を持ちつつ、純粋なオンディスクでメモリより大きなインデックスへとスケールすると主張している。

ℹ️ 情報

世の中のデータベースベンダーの中で、LanceDBはこの点で際立っている。なぜなら、サポートしている全てのインデックスがディスクベースである唯一のベンダーだからである。ベクトルクエリに応答する際、インデックスファイルから関連するページのみがディスクから読み込まれ、メモリにキャッシュされる。LanceDBでこれができる最大の理由は、オンディスクの高速なベクトル検索に最適化された新しいオープンソースのカラム型ベクトルストアであるLanceの上に構築されているからである。

検討すべきポイント:

  • 自分のデータセットが非常に大きい場合(>1000万ベクトル)、メモリ消費をどのように削減できるか?このような場合、保存されるベクトルの次元数を減らす、グラフの最大接続数を調整する(HNSWを使用している場合)、または直積量子化を追加する(DBがサポートしている場合)などが有効になる。
  • 自分のデータベースにはベクトルをディスク上に保存するオプションがあるか?もしある場合は、それがクエリ速度にどのように影響するか?常に自分のデータとユースケースでテストすべきである!

6.疎ベクト・ストレージと密ベクトルストレージ

sentence-transformersや類似のモデルによって生成されるベクトルの埋め込みは密である。つまり、それらは非ゼロの浮動小数点数で完全に構成されている。しかし、ドキュメントごとの相対的な単語の頻度を計算する疎ベクトルも使用することが可能であり、この場合ベクトルの大部分の値はゼロになる。疎ベクトルは、BM25やSPLADE(Sparse Lexical AnD Expansion)のようなアルゴリズムによって一般的に生成される。 Elasticsearchは商用の英語用事前学習済み疎ベクトルモデル、ELSER (Elasticsearch Learned Sparse Encoder) を提供しており、その次元数はおよそ30,000だが、疎であるため、同程度の長さの密ベクトルに比べてよりも計算と保存のコストがはるかに低い。

sentence-transformersなどの多くのtransformerモデルの登場により、ドキュメントから密ベクトルを生成することは以前にも増して簡単(また手頃)になった。密ベクトルの主な利点は、transformerによる基本的な埋め込みのおかげで、疎ベクトルよりも言語のセマンティクスをはるかに良く圧縮できることである ー ただしインデックス作成にはコストがかかるため、1億ベクトルのオーダーのデータセットを扱う際には十分に考慮しなければならない。

検討すべきポイント:

  • セマンティック検索の重要度はどれくらいか?非常に重要なのであれば、密ベクトルが絶対的な選択肢である。
  • インデックス作成の速度とレイテンシの重要度はどれくらいか?これらが非常に重要な制約である場合、疎ベクトルの検討も価値があるかもしれない(ただし、セマンティック検索の観点からは密ベクトルほど性能は発揮しないだろう)。

7.全文検索とベクトル検索のハイブリッド戦略

ベクトル検索は万能薬ではないということはよく知られている。Colin Harman氏の素晴らしいブログ記事[9]をもう一度引用しよう。この重要な事項を彼はこう述べている:

残念ながら、エンタープライズレベルのアプリケーションにおいて、単純なベクトル検索はしばしば間違った解決策である。多くの専門家はこれを理解しており、情報検索システムの一部としてベクトル検索を使用している。

これの主な理由は、ベクトル検索は正確な一致よりも意味的に類似した結果をランク付けすることができるものであるが、多くのユースケースでは、意味的に類似した一致よりも完全一致の方に高いスコアをつけたい場合があるからである。また、言語や用語が進化するにつれて、特定の用語の「意味」が変わることがあり、これらは基礎となる埋め込みで十分に捉えられないことがある。キーワードベースの全文検索結果のスコアを使ってベクトル検索の結果をリランキングしたり、複数のインデックス戦略の組み合わせ(転置インデックスとベクトルインデックスの組み合わせ、など)により、結果の質を改善することができる。Vespaは、HNSW-IVFインデックスを提供するハイブリッド検索エンジンとして、良い例である。[10]

リランキングによってこのトレードオフを処理するいくつかのテクニックを以下に説明する。

  • Naive Fallback Approach: このアプローチは、MeilisearchやElasticsearchのようなBM25で実装されたキーワード検索をタイプしながら開始し、高レイテンシのベクトル検索とキーワード検索の結果を線形に組み合わせる「フォールバック」戦略を使用する。これは最も単純なアプローチであり、関連性の観点から必ずしも最良の結果をもたらすわけではない。
  • Reciprocal Rank Fusion(RRF):このアプローチは、疎と密のベクトルから得られる逆ランクを合計して、融合されたランキングスコアを提供する。ElasticsearchやWeaviate[11]のようなデータベースは、多くのRRF方法のいずれかを使用したハイブリッド検索を提供している。
  • 交差-エンコーダーリランキング: これは、ハイブリッドスコアのリランキングのための最も先進的な方法である。交差エンコーディング損失関数を持つニューラルbi-エンコーダーを使用して、疎/密のランキングスコアを融合する。これにより、最も高コストなアプローチによるリランキングの高いレイテンシの代償として、通常最も良い結果が得られる。これらのソリューションは通常、ベクトルデータベースで直接提供されるわけではない – ベクトルDBの下流でカスタム検索エンジンを構築して、リランキングを実行する必要がある。sentence-transformersライブラリの作者で、現在Cohere.aiに在籍しているNils Reimers氏は、以下のWeaviateポッドキャストのエピソードで、まさにそのようなソリューションを詳しく説明している。😄

https://youtu.be/KITxQzV97jw

検討すべきポイント:

  • 選択したデータベースは、しっかりとしたハイブリッド検索戦略を実装しているか?それとも、ベクトルデータベースの下流で手作業の解決策を構築する必要があるか?
  • リランク戦略によって検索待ち時間はどのように影響を受けるか?
  • 精度を向上させることで(例えば、交差-エンコーダーリランキングを通じて)検索結果にどれだけのレイテンシを追加できる余裕があるか?

8.フィルタリング戦略

検索において、実際のクエリは、特定のキーワードを尋ねるような単純なテキストクエリであることはまれである。通常、他のメタデータ属性に対するフィルタリングを伴う。特定のサイズの衣料品検索(パンツ、ジーンズなど)に関する小売の例を考えてみよう。これらのフィルタを検索結果に適用する方法は、結果の品質に大きな影響を与える可能性がある。

  • 事前フィルタリング検索: このアプローチでは、ベクトル探索を行う前に単純にサイズフィルターを適用する。自然な試みのように聞こえるが、これはHSNWグラフが非連結のコンポーネントに崩壊する可能性がある(これが起こる閾値を定義しているパーコレーション理論[12]による)。例として、ユーザーが検索カタログにないサイズ28の「ジーンズ」を探していた場合、正しい方法は、少なくとも同じようなサイズの関連アイテム(例えば「パンツ」)を表示することだろう。しかし、事前フィルタリングは、サイズ基準を満たさないすべての用語を検索から積極的に除外するため、完全なグラフが探索されず、関連する結果を逃してしまうのである。

  • 事後フィルタリング検索: このアプローチは、クエリベクトル("jeans")のtop-k(上位k個)の最近傍を返し、全ての "jeans "の結果が検索された後、マッチするサイズに基づいてそれらをフィルタリングする。しかし、これにも問題がある ー 全てのクエリで常に同じ数の結果を得るわけではなく、フィルタリングされる属性、例えばサイズ28がデータセット全体のごく一部である場合、結果がほとんど得られないこともある!

  • カスタムフィルタリング検索: 多くのデータベースが事前フィルタリングや事後フィルタリングの中間に位置する方法を適用している。たとえば、Weaviateは、転置インデックスのシャードとHNSWインデックスのシャードを並列に保存し、転置インデックスを使用して、より効果的に事前フィルタリングを行う ー 転置インデックスから得られる「許可リスト」は非常に大きなリストだが、セマンティクスを考慮したHNSWインデックスを経由することで、より効果的に検索を行うことができる。Qdrantは、インデックス時にカテゴリ間でエッジを形成することで、幅広い条件下で連結されたHNSWグラフを保証する、プリフィルタリングとポストフィルタリングの中間の独自のフィルタリング方法を使用している。

📄 注記
ベクトル検索で結果をフィルタリングするための「万能な」ソリューションは存在しない。複数の緩和戦略が存在しており、Weaviateのようにキーワードを使用して検索を補助するために追加のIVFインデックスを構築したり、またはQdrantのようにカテゴリ間に追加のHNSWグラフ接続を作成してフィルタリング中の検索ですべてのバケットを考慮する、などの方法がある。この分野は絶えず進化しており、これらの多くのトレードオフが存在するために、関連性の高い検索は非常に難しい問題である。

検討すべきポイント:

  • 自分が選択したデータベースは、事前/事後のフィルタリングをどのように処理するのか?
  • 自分が実行しようとしているクエリのクラスについて、自分のデータで事前/事後のフィルタリング戦略はどれぐらいうまく機能するか?

結論

ふぅー!ベクトルデータベースの内部を理解するための長い道のりだった。私は2023年のほとんどをこのトピックについて深く考えることに費やし、多くの複雑な問題に取り組み、この技術とツールを試している開発者やCEO、その他多くの人々と興味深い会話をたくさん行ってきた。🤓

ベクトルデータベースはこの急速に変化している領域で進化を続けているが、私がこのシリーズから最も学んだことは、「万能」のソリューションは存在しないということである。ベクトルデータベースを選択する最良の方法は、まず自分のユースケースの要件と制約を理解し、次に自分のデータで様々なソリューションをテストすることである。

私の経験では、専用ソリューションの方が優れた選択肢である。なぜなら、より幅広い機能を持ち、まっさらな状態からスタートするため最先端のソリューションを実装でき、既存のベンダーが優先順位をつけられないような多くの最適化も含まれているためである。この先、Rust 🦀で作られた2つのデータベース、QdrantとLanceDBに特に期待をしており、私がPOCや実験を行う際に頼りにしているソリューションである。どちらも全く異なる方法で新しいレベルの革新を行っており、最も重要なのは、どちらも開発者ファーストの哲学を持ち、コミュニティが急速に成長していることである。どちらのベンダーを選ぶにせよ、私や他の多くの人たちと一緒に、これらのツールをさらに探求することをお勧めする!🤓

ポッドキャストを聞くのが好きなら、私はPractical AI Podcastでこれらのトピックについて詳しく話しているので聞いてみてほしい。楽しんで学び、コーディングを続けてください!🚀

このシリーズの他の記事


脚注
  1. "Teach your DuckDB to fly", MotherDuck ↩︎

  2. "Developer-friendly, serverless vector database": LanceDB ↩︎

  3. "Deployment": Chroma docs ↩︎

  4. "Zilliz pricing", zilliz.com ↩︎

  5. "pgvector vs. Qdrant", Nirant Kasliwal’s blog ↩︎

  6. "Managing data in massive-scale vector search engine", Milvus blog ↩︎

  7. "ANN indexes FAQ", LanceDB docs ↩︎

  8. "On-disk index", Milvus docs ↩︎

  9. "Beware tunnel vision in AI retrieval: Colin Harman", Substack ↩︎

  10. "Billion-scale vector search using hybrid HNSW", by Jo Kristian Bergum ↩︎

  11. "Hybrid search explained, Weaviate blog", by Erika Cardenas ↩︎

  12. "Filterable HNSW", Qdrant blog ↩︎

GitHubで編集を提案