RedditでのANN検索のためのベクトルデータベースの選択
この投稿はRedditのスタッフ・ソフトウェア・エンジニアであるChris Fournieによって書かれ、元々は Redditに掲載されたものである。
2024年、Redditチームは近似最近傍(ANN)ベクトル検索を実行するために様々なソリューションを使用した。GoogleのVertex AI Vector Searchや、いくつかの大きなデータセットにApache SolrのANNベクトル検索を使用する実験から、小さなデータセット(縦方向にスケーリングされたサイドカーでホストされている)にはFacebookのFAISSライブラリまで。Redditでは、費用対効果が高く、希望する検索機能を備え、Redditサイズのデータに拡張できる、幅広くサポートされたANNベクトル検索ソリューションを求めるチームが増えていた。このニーズに応えるため、2025年、私たちはRedditチームにとって理想的なベクトルデータベースを探しました。
この投稿では、現在のRedditのニーズに最適なベクトルデータベースを選択するために使用したプロセスを説明します。全体として最適なベクターデータベースや、あらゆる状況において最も必要な機能要件と非機能要件のセットを説明するものではありません。Redditとそのエンジニアリング文化が、ベクターデータベースを選択する際に何を重視し、何を優先したかを説明しています。この投稿は、独自の要件収集と評価のインスピレーションになるかもしれませんが、組織にはそれぞれ独自の文化、価値観、ニーズがあります。
評価プロセス
全体的な選定ステップは次のとおりです:
1.チームからコンテキストを収集する
2.ソリューションを定性的に評価
3.上位候補を定量的に評価
4.最終選考
1.チームからコンテキストを収集
ANNベクトル検索に興味を持つチームから、3つのコンテキストを収集した:
機能要件(例:ベクトル検索と語彙検索のハイブリッド?範囲検索クエリ?ベクトル以外の属性によるフィルタリング?)
非機能要件(例:1Bベクトルをサポートできるか? P99レイテンシ<100msを達成できるか?)
ベクターデータベースはすでにチームが興味を持っていた
チームに要件をヒアリングするのは簡単なことではない。多くのチームは、自分たちが現在どのように問題を解決しているかという観点から自分たちのニーズを説明します。
例えば、あるチームはすでにFAISSをANNベクトル検索に使用しており、新しいソリューションは検索呼び出し1回につき10Kの結果を効率的に返さなければならないと述べていた。さらに議論してみると、10Kの結果の理由は、ポストホックフィルタリングを行う必要があるからであり、FAISSはクエリ時にANN結果をフィルタリングする機能を提供していない。彼らの実際の問題は、フィルタリングが必要であるということであり、効率的なフィルタリングを提供するソリューションがあればそれで十分であり、10Kの結果を返すことは、単にリコールを向上させるために必要な回避策であった。彼らの理想は、最近傍を見つける前にコレクション全体を事前にフィルタリングすることである。
チームがすでに使用している、あるいは興味を持っているベクターデータベースを尋ねることも貴重だった。少なくとも1つのチームが現在のソリューションに肯定的な見解を持っていれば、ベクトルデータベースが全社で共有できる有用なソリューションになり得るというサインだ。あるソリューションに対して否定的な意見しかないチームは、選択肢に含めるべきではない。チームが興味を持っているソリューションを受け入れることは、チームがプロセスに加わっていると感じ、評価すべき有力候補の初期リストを形成するのに役立ったことを確認する方法でもあった。
2.ソリューションを定性的に評価
チームが興味を持ったソリューションのリストから始めて、どのANNベクトル検索ソリューションが我々のニーズに最も適しているかを定性的に評価するために、我々は以下のことを行った:
各ソリューションを調査し、各要件をどの程度満たしているかを、その要件の重み付けされた重要度に対して採点した。
定性的な基準と議論に基づいてソリューションを削除
定量的にテストする上位N個のソリューションを選択
ANNベクトル検索ソリューションのスタートリストには以下のものが含まれていた:
Qdrant
Weviate
オープンサーチ
Pgvector (既にRDBMSとしてPostgresを使っている)
Redis (KVストアとキャッシュとして使用済み)
Cassandra (すでに非ANN検索に使用)
Solr(すでに字句検索に使用し、ベクトル検索も実験済み)
Vespa
Pinecone
Vertex AI(ANNベクトル検索に使用済み)
次に、各チームから挙げられたすべての機能要件と非機能要件に加え、私たちのエンジニアリングの価値と目標を表すいくつかの制約を取り、スプレッドシートにそれらの行を作成し、それらがどの程度重要であるかを量りました(1から3まで。)
比較するソリューションごとに、各システムがどの程度その要件を満たしているかを(0から3の尺度で)評価した(下表)。この方法での採点はやや主観的であったため、1つのシステムを選び、その採点例を根拠とともに文書で示し、レビュアーにそれらの例を参照させた。また、各得点値の付け方について、次のような指針を示した:
0: サポートなし/要件サポートの証拠なし
1: 基本的または不十分な要件サポート
2: 要件が合理的にサポートされている
3: 類似のソリューションを凌駕する強固な要件サポート
次に、ソリューションの要件スコアとその要件の重要度の積の合計を取ることで、各ソリューションの総合スコアを作成した(例えば、Qdrantは重要度2の再ランク付け/スコア結合に3点を獲得したため、3 x 2 = 6となり、これをすべての行について繰り返し、合計する)。最後に、ソリューションのランク付けや議論、そしてどの要件が最も重要であるかの基準として使用できる総合的なスコアが得られます(スコアは最終的な決定に使用されるのではなく、議論のツールとして使用されることに注意してください)。
編集部注: このレビューはMilvus 2.4に基づいています。その後、Milvus 2.5、 Milvus 2.6が リリースされ、Milvus 3.0が目前に迫っているため、いくつかの数値は古くなっているかもしれません。それでも、この比較は依然として強力な洞察を提供し、非常に有用であることに変わりはない。
| カテゴリー | 重要度 | Qdrant | Milvus (2.4) | カサンドラ | Weviate | ソラー | バーテックスAI |
| 検索タイプ | |||||||
| ハイブリッド検索 | 1 | 3 | 2 | 0 | 2 | 2 | 2 |
| キーワード検索 | 1 | 2 | 2 | 2 | 2 | 3 | 1 |
| 近似NN探索 | 3 | 3 | 3 | 2 | 2 | 2 | 2 |
| 範囲検索 | 1 | 3 | 3 | 2 | 2 | 0 | 0 |
| 再ランキング/得点の組み合わせ | 2 | 3 | 2 | 0 | 2 | 2 | 1 |
| インデックス作成方法 | |||||||
| HNSW | 3 | 3 | 3 | 2 | 2 | 2 | 0 |
| 複数のインデックス方式をサポート | 3 | 0 | 3 | 1 | 2 | 1 | 1 |
| 量子化 | 1 | 3 | 3 | 0 | 3 | 0 | 0 |
| ロカリティ・センシティブ・ハッシング(LSH) | 1 | 0 | 0Note:Milvus 2.6 がサポートしています。 | 0 | 0 | 0 | 0 |
| データ | |||||||
| float以外のベクトル型 | 1 | 2 | 2 | 0 | 2 | 2 | 0 |
| ベクトル上のメタデータ属性(複数の属性、大きなレコードサイズなどをサポート) | 3 | 3 | 2 | 2 | 2 | 2 | 1 |
| メタデータのフィルタリングオプション(メタデータでフィルタリング可能、事前/事後フィルタリングあり) | 2 | 3 | 2 | 2 | 2 | 3 | 2 |
| メタデータ属性のデータ型(堅牢なスキーマ、bool、int、string、json、arrayなど) | 1 | 3 | 3 | 2 | 2 | 3 | 1 |
| メタデータ属性の制限(レンジクエリ、例:10 < x < 15) | 1 | 3 | 3 | 2 | 2 | 2 | 1 |
| 属性による結果の多様性(例:各サブレディットからの回答結果がN件以下であること) | 1 | 2 | 1 | 2 | 3 | 3 | 0 |
| スケール | |||||||
| 数億ベクトル指数 | 3 | 2 | 3 | 1 | 2 | 3 | |
| 億ベクトル指数 | 1 | 2 | 2 | 1 | 2 | 2 | |
| 少なくとも2kのサポートベクトル | 2 | 2 | 2 | 2 | 2 | 1 | 1 |
| 2k以上のサポートベクトル | 2 | 2 | 2 | 2 | 1 | 1 | 1 |
| P95 レイテンシ 50-100ms @ X QPS | 3 | 2 | 2 | 2 | 1 | 1 | 2 |
| P99 レイテンシ <= 10ms @ X QPS | 3 | 2 | 2 | 2 | 3 | 1 | 2 |
| 99.9% 可用性検索 | 2 | 2 | 2 | 3 | 2 | 2 | 2 |
| 99.99%の可用性 インデックス/ストレージ | 2 | 1 | 1 | 3 | 2 | 2 | 2 |
| ストレージ運用 | |||||||
| AWSでホスティング可能 | 3 | 2 | 2 | 2 | 2 | 3 | 0 |
| マルチ・リージョン | 1 | 1 | 2 | 3 | 1 | 2 | 2 |
| ゼロダウンタイムアップグレード | 1 | 2 | 2 | 3 | 2 | 2 | 1 |
| マルチクラウド | 1 | 3 | 3 | 3 | 2 | 2 | 0 |
| API/ライブラリ | |||||||
| gRPC | 2 | 2 | 2 | 2 | 2 | 0 | 2 |
| RESTful API | 1 | 3 | 2 | 2 | 2 | 1 | 2 |
| 図書館へ行く | 3 | 2 | 2 | 2 | 2 | 1 | 2 |
| Javaライブラリ | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
| パイソン | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
| その他の言語(C++、Rubyなど) | 1 | 2 | 2 | 3 | 2 | 2 | 2 |
| ランタイムオペレーション | |||||||
| プロメテウスのメトリクス | 3 | 2 | 2 | 2 | 3 | 2 | 0 |
| DB の基本操作 | 3 | 2 | 2 | 2 | 2 | 2 | 2 |
| アップサート | 2 | 2 | 2 | 2 | 1 | 2 | 2 |
| Kubernetes オペレーター | 2 | 2 | 2 | 2 | 2 | 2 | 0 |
| 結果のページネーション | 2 | 2 | 2 | 2 | 2 | 2 | 0 |
| IDによるルックアップの埋め込み | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
| エンベッディングを候補IDと候補スコアで返す | 1 | 3 | 2 | 2 | 2 | 2 | 2 |
| ユーザー提供ID | 2 | 2 | 2 | 2 | 2 | 2 | 2 |
| 大規模なバッチ検索が可能 | 1 | 2 | 1 | 1 | 2 | 1 | 2 |
| バックアップ/スナップショット:データベース全体のバックアップを作成する機能をサポートしています。 | 1 | 2 | 2 | 2 | 3 | 3 | 2 |
| 効率的な大規模インデックスのサポート(コールドストレージとホットストレージの区別) | 1 | 3 | 2 | 2 | 2 | 1 | 2 |
| サポート/コミュニティ | |||||||
| ベンダーの中立性 | 3 | 3 | 2 | 3 | 2 | 3 | 0 |
| 堅牢なAPIサポート | 3 | 3 | 3 | 2 | 2 | 2 | 2 |
| ベンダーサポート | 2 | 2 | 2 | 2 | 2 | 2 | 0 |
| コミュニティ速度 | 2 | 3 | 2 | 2 | 2 | 2 | 0 |
| 生産ユーザーベース | 2 | 3 | 3 | 2 | 2 | 1 | 2 |
| コミュニティ感 | 1 | 3 | 2 | 2 | 2 | 2 | 1 |
| Githubスター | 1 | 2 | 2 | 2 | 2 | 2 | 0 |
| 構成 | |||||||
| 秘密の取り扱い | 2 | 2 | 2 | 2 | 1 | 2 | 2 |
| ソース | |||||||
| オープンソース | 3 | 3 | 3 | 3 | 2 | 3 | 0 |
| 言語 | 2 | 3 | 3 | 2 | 3 | 2 | 0 |
| リリース | 2 | 3 | 3 | 2 | 2 | 2 | 2 |
| 上流試験 | 1 | 2 | 3 | 3 | 2 | 2 | 2 |
| 文書の入手可能性 | 3 | 3 | 3 | 2 | 1 | 2 | 1 |
| コスト | |||||||
| 費用対効果 | 2 | 2 | 2 | 2 | 2 | 2 | 1 |
| パフォーマンス | |||||||
| CPU、メモリ、ディスクのリソース使用率のチューニングをサポート | 3 | 2 | 2 | 2 | 2 | 2 | 2 |
| マルチノード(ポッド)シャーディング | 3 | 2 | 2 | 3 | 2 | 2 | 2 |
| 待ち時間とスループットのバランスをとるためにシステムをチューニングする能力がある。 | 2 | 2 | 2 | 3 | 2 | 2 | 2 |
| ユーザー定義パーティショニング(書き込み) | 1 | 3 | 2 | 3 | 1 | 2 | 0 |
| マルチテナント | 1 | 3 | 2 | 1 | 3 | 2 | 2 |
| パーティショニング | 2 | 2 | 2 | 3 | 2 | 2 | 2 |
| レプリケーション | 2 | 2 | 2 | 3 | 2 | 2 | 2 |
| 冗長性 | 1 | 2 | 2 | 3 | 2 | 2 | 2 |
| 自動フェイルオーバー | 3 | 2 | 0 注:Milvus 2.6がサポートしています。 | 3 | 2 | 2 | 2 |
| ロードバランシング | 2 | 2 | 2 | 3 | 2 | 2 | 2 |
| GPUサポート | 1 | 0 | 2 | 0 | 0 | 0 | 0 |
| クドラント | Milvus | カサンドラ | Weviate | ソル | バーテックスAI | ||
| ソリューション全体のスコア | 292 | 281 | 264 | 250 | 242 | 173 |
私たちは、さまざまなシステムの総合スコアと要件スコアについて議論し、要件の重要性を適切に重み付けしたかどうか、また、要件の中には、中核的な制約と考えるべきほど重要なものがあるかどうかを理解しようと努めました。そのような要件の 1 つとして、ソリューションがオープンソースであるかどうかが挙げられた。オープンソースソフトウェアへの貢献と使用は、Redditのエンジニアリング文化の重要な部分です。そのため、ホスティングのみのソリューション(Vertex AI、Pinecone)は検討対象から外しました。
ディスカッションの中で、いくつかの重要な要件が私たちにとって非常に重要であることがわかりました:
スケールと信頼性:100M以上、あるいは1B以上のベクターでソリューションを実行している他社の証拠を見たかった。
コミュニティ:私たちは、急速に成熟しつつあるこの分野で、勢いのある健全なコミュニティを持つソリューションを求めていました。
より多くのユースケース(日付、ブーリアンなどによるフィルタリング)を可能にする、表現力豊かなメタデータ・タイプとフィルタリング。
HNSWやDiskANNだけでなく、複数のインデックスタイプをサポートすることで、多くのユニークなユースケースのパフォーマンスを向上させる。
ディスカッションの結果、主要な要件を絞り込み、定量的にテストすることにしました:
Qdrant
Milvus
Vespa
Weviate
残念ながら、このような決定には時間とリソースが必要です。予算を考慮し、QdrantとMilvusをテストし、VespaとWeviateのテストはストレッチゴールとして残すことにしました。
QdrantとMilvusの比較は、2つの異なるアーキテクチャの興味深いテストでもありました:
Qdrant:Qdrant:すべてのANNベクトルデータベース操作を実行する同種のノードタイプ
Milvus: 異種ノードタイプ(Milvus; 一つはクエリ、もう一つはインデックス作成、もう一つはデータインジェスト、プロキシなど。)
どれがセットアップが簡単だったか?どれが実行しやすかったか?そして、私たちが気にかけているユースケースやスケールに対して、どれが最も良いパフォーマンスなのか?このような疑問に答えながら、ソリューションを定量的に比較した。
3.トップ候補を定量的に評価
私たちは、各ソリューションのスケーラビリティをよりよく理解し、その過程で、各ソリューションのセットアップ、設定、保守、運用がどのようなものかを体験したいと考えました。これを行うために、3つの異なるユースケースのドキュメントとクエリベクトルの3つのデータセットを収集し、Kubernetes内で同様のリソースで各ソリューションをセットアップし、各ソリューションにドキュメントをロードし、GrafanaのK6を使用して同一のクエリロードを送信しました。
私たちは、スループット、各ソリューションの限界点、スループットとレイテンシの関係、負荷がかかった状態でノードを失った場合の反応(エラー率、レイテンシへの影響など)をテストしました。特に興味深かったのは、レイテンシに対するフィルタリングの効果だった。また、ドキュメントに記載されている機能(アップサート、削除、IDによる取得、ユーザー管理など)が説明どおりに機能するかどうかを検証し、それらのAPIの人間工学を体験するための単純なYES/NOテストも行った。
テストはMilvus v2.4とQdrant v1.12で行いました。時間的制約のため、全てのタイプのインデックス設定を網羅的にチューニング、テストしたわけではありません。同様の設定を各ソリューションで使用し、高いANNリコールにバイアスをかけ、テストはHNSWインデックスのパフォーマンスに焦点を当てました。同様の CPU とメモリリソースが各ソリューションに与えられた。
我々の実験では、2つのソリューションの間にいくつかの興味深い違いを発見した。以下の実験では、各ソリューションは、HNSW、M=16、efConstruction=100で、それぞれ384次元の約340MのRedditポストベクトルを持つ。
ある実験では、同じクエリスループット(同時にインジェストを行わず100QPS)の場合、フィルタリングを追加することで、MilvusのレイテンシがQdrantよりも影響を受けることがわかりました。
フィルタリングによるポストクエリのレイテンシ
もう一つ、MilvusよりもQdrantの方が、インジェストとクエリ負荷の相互作用が大きいことがわかりました(スループット一定で下図)。Milvusはインジェストとクエリのトラフィックを別々のノードで行っているのに対し、Qdrantはインジェストとクエリのトラフィックを同じノードで行っています。
インジェスト時のクエリレイテンシ@100 QPSの投稿
属性による結果の多様性(例えば、レスポンスで各サブレディットからN件以下の結果を得る)をテストしたところ、同じスループットでMilvusはQdrantよりもレイテンシが悪いことがわかりました(100 QPSの場合)。
結果の多様性とポストクエリの待ち時間
さらに、データの複製を増やした場合(複製係数RFを1から2に増やした場合)、各ソリューションがどの程度効果的にスケールするかを確認しました。RF=1の場合、QdrantはMilvusよりも高いスループットで満足のいくレイテンシーを得ることができました(テストがエラーなく完了しなかったため、高いQPSは表示されていません)。
Qdrantは様々なスループットでRF=1のレイテンシを実現
Milvusは様々なスループットでRF=1のレイテンシを実現。
レプリケーション係数を増加させると、Qdrantのp99レイテンシは改善されたが、MilvusはQdrantよりも高いスループットを維持し、レイテンシも許容範囲内であった(Qdrant 400 QPSはレイテンシが高くエラーが発生したためテストが完了しなかったため表示されていない)。
Milvusは様々なスループットでRF=2のレイテンシを記録。
Qdrantはスループットを変えながらRF=2のレイテンシを記録
時間的制約のため、我々のデータセットにおけるソリューション間の ANN リコールを比較するのに十分な時間がなかったが、一般に利用可能なデータセットでhttps://ann-benchmarks.com/から提供されたソリューションの ANN リコール測定値を考慮した。
4.最終選択
性能面では、あまりチューニングせず、HNSWのみを使用した場合、Qdrantの方がMilvusよりも多くのテストでレイテンシが優れているように見えた。しかし、Milvusはレプリケーションを増やせば増やすほどスケールし、マルチノード型のアーキテクチャのため、インジェストとクエリ負荷の分離が優れているように見えました。
運用面では、Milvusのアーキテクチャの複雑さ(複数のノードタイプ、Kafkaのような外部ライトアヘッドログとetcdのようなメタデータストアへの依存)にもかかわらず、どちらのソリューションもQdrantよりデバッグや修正が容易でした。Milvusはまた、コレクションのレプリケーション係数を増加させる際に自動的にリバランスを行います。一方、オープンソースのQdrantでは、レプリケーション係数を増加させるために手動でシャードを作成または削除する必要があります(この機能は、私たち自身で構築するか、オープンソースでないバージョンを使用する必要がありました)。
MilvusはQdrantよりも "Reddit型 "の技術であり、我々の他の技術スタックとの共通点が多い。Milvusは、私たちが好むバックエンドプログラミング言語であるGolangで書かれているため、Rustで書かれているQdrantよりも貢献しやすい。MilvusはQdrantに比べ、オープンソースの割にプロジェクトの速度が速く、私たちの主要な要件を満たしていました。
最終的には、どちらのソリューションも私たちの要求のほとんどを満たしており、場合によってはQdrantの方がパフォーマンスが優れていることもありましたが、私たちはMilvusの方がより拡張でき、より快適に運用でき、Qdrantよりも私たちの組織にマッチしていると感じました。VespaとWeaviateをテストする時間がもっとあれば良かったのですが、組織への適合性(VespaはJavaベース)やアーキテクチャ(WeaviateはQdrantと同じシングルノードタイプ)の観点から、これらの製品も選ばれたのかもしれません。
キーポイント
与えられた要件に挑戦し、既存のソリューションのバイアスを取り除く。
候補となるソリューションに点数をつけ、それをすべてとしてではなく、必須要件の議論に役立てる。
ソリューションを定量的に評価するが、その過程で、そのソリューションで作業することがどのようなものかをメモする。
単にソリューションの性能が最高だからではなく、メンテナンス、コスト、使いやすさ、パフォーマンスの観点から、組織内で最もフィットするソリューションを選ぶ。
謝辞
この評価作業は、Ben Kochie、Charles Njoroge、Amit Kumar、そして私が行った。また、アニー・ヤン、コンラッド・ライヒ、サブリナ・コング、アンドリュー・ジョンソンなど、この作業に貢献してくれた他の人々にも感謝する。
編集者コメント
Milvusをベクトル検索ワークロードに採用していただいただけでなく、このような詳細かつ公正な評価を公表するために時間を割いていただいたRedditエンジニアリングチームに心から感謝したい。実際のエンジニアリングチームがどのようにデータベースを比較しているのか、このようなレベルの透明性を見ることは稀であり、彼らの記事は、成長するベクトルデータベースの状況を理解しようとしているMilvusコミュニティ(およびそれ以外)の誰にとっても役に立つだろう。
クリスが投稿で述べたように、単一の "ベスト "ベクターデータベースは存在しない。重要なのは、システムがあなたの作業負荷、制約、運用哲学に合っているかどうかだ。Redditの比較はその現実をよく反映している。Milvusはすべてのカテゴリーでトップではないが、異なるデータモデルやパフォーマンス目標間のトレードオフを考えれば、それは完全に予想されることだ。
ひとつ明確にしておきたいことがある:Redditの評価では、当時の安定リリースであったMilvus 2.4を使用している。LSHやいくつかのインデックスの最適化など、いくつかの機能は2.4ではまだ存在していなかったか、成熟していなかったため、いくつかのスコアは当然その古いベースラインを反映しています。それ以来、Milvus 2.5、そしてMilvus 2.6をリリースし、パフォーマンス、効率性、柔軟性の面で全く異なるシステムとなっている。コミュニティーの反応は強く、すでに多くのチームがアップグレードを行いました。
Milvus 2.6の新機能を簡単にご紹介します:
RaBitQ 1ビット量子化により、メモリ使用量を最大72%削減し、クエリを4倍高速化。
インテリジェント階層型ストレージによる50%のコスト削減
Elasticsearchと比較して4倍高速なBM25全文検索
新しいパスインデックスによる100倍高速なJSONフィルタリング
より新鮮な検索をより低コストで実現する新しいゼロディスクアーキテクチャ
パイプラインを組み込むための、よりシンプルな「データイン、データアウト」ワークフロー
大規模なマルチテナント環境に対応するための100K以上のコレクションのサポート
詳細がお知りになりたい方は、こちらをご覧ください:
機能についてのご質問やディープダイブをご希望ですか?私たちの Discord チャンネルに参加するか、 GitHub に課題を提出してください。また、 Milvusオフィスアワーを通して、20分間の1対1のセッションを予約し、洞察、ガイダンス、質問への回答を得ることもできます。
Try Managed Milvus for Free
Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.
Get StartedLike the article? Spread the word



