ベクトルデータベース
Vector Database ・ べくとるでーたべーす
埋め込みベクトルを格納し、「意味が近いデータ」を近似最近傍探索で高速に探すデータベース。
✦ 30秒で試す — 航海言葉が一致しなくても「意味が近い」文書を探し当てるHNSW が返す点は、本当にいちばん近い点?予想してみる概要
ベクトルデータベースは、埋め込みによって作られた高次元のベクトルを大量に格納し、「このベクトルに最も近いものはどれか」という近傍検索を高速に実行するために設計されたデータベースです。通常のデータベースが「id = 42 の行」「価格が1000円未満の商品」のような条件の一致で探すのに対し、ベクトルデータベースは「意味が近い順に上位10件」という距離の近さで探します。近さの測り方には、ベクトルの向きの近さ(コサイン類似度)や内積、ふつうの直線距離(ユークリッド距離)が使われます。
登場する場面の代表が RAG(検索拡張生成)です。社内文書を埋め込みベクトルにして格納しておき、利用者の質問が来たら意味の近い文書を取り出して大規模言語モデルに渡す。この「取り出す」部分の基盤がベクトルデータベースです。ほかにも類似画像の検索、推薦、重複コンテンツの検出など、「似ているものを探す」機能の裏側で広く使われています。
Pinecone、Milvus、Qdrant、Weaviate のような専用製品のほか、PostgreSQL の拡張 pgvector のように既存のデータベースにベクトル検索の機能を足す形もあり、どちらを選ぶかが設計の定番の論点になっています。
なぜ生まれたか
近傍検索そのものは単純で、クエリのベクトルと全データの距離を1件ずつ計算して並べ替えれば、正確な答えが出ます。しかしこの全件走査は、件数×次元数に比例する計算です。1536次元のベクトルが1000万件あれば、1回の検索で百数十億回の掛け算が要り、リクエストのたびに実行するには遅すぎます。しかも、従来のデータベースのインデックスはここでは役に立ちません。B木は「値の大小」で1列に並べられるデータを前提にしていますが、高次元空間の「近さ」には、1列に並べる順序がそもそも存在しないからです。次元が高くなると、空間を箱に区切って絞り込む k-d 木のような古典的なアルゴリズムも、調べる箱が増えすぎて全件走査とほとんど変わらなくなります(次元の呪い)。
この壁を破ったのが近似最近傍探索(ANN: Approximate Nearest Neighbor)です。「厳密な最近傍は諦め、ほぼ確実に近い候補を桁違いに速く見つける」という割り切りで、全件走査なら数秒かかる検索をミリ秒台に縮めます。意味の検索では「上位10件のうち1件が11位と入れ替わる」程度の誤差は実用上ほとんど問題にならないので、この近似は割に合う取引でした。2016年に Malkov と Yashunin が HNSW を発表し、2017年に Meta(当時の Facebook)が高速な ANN ライブラリ Faiss を公開するなど、2010年代後半に実用的なアルゴリズムと実装がそろいます。そこへ大規模言語モデル(LLM)の普及で RAG の需要が爆発し、ANN のインデックスを中核に据えた専用のデータベースが一気に広まりました。
詳細
ANN インデックスの仕組み — HNSW を例に
いま最も広く使われる ANN のアルゴリズムが HNSW(Hierarchical Navigable Small World)です。まず、全ベクトルを「近いもの同士を辺でつないだグラフ」にしておきます。検索では、どこかの点から出発し、いまいる点の隣人の中でクエリにより近い点へ移る、という貪欲な移動を、それ以上近づけなくなるまで繰り返します。
ただし、平らなグラフ1枚だけでは、遠くから出発すると目的地まで何百歩もかかります。そこで HNSW は、グラフを何層にも重ねます。すべての点は最下層に入り、そのうちランダムに選ばれた一部だけが1つ上の層にも入り、さらにその一部がもう1つ上の層にも入る、というように、上の層ほど点がまばらで辺が長くなります。検索は最上層から始め、高速道路で目的地の近くまで一気に移動してから、層を降りるたびに一般道で細かく詰めます。この階層のおかげで、数千万件からでも数百回程度の距離計算で近傍にたどり着けます。
最下層では、1本道を貪欲に進むだけだと、近くに見えて実は袋小路という点で止まり、真の最近傍を取り逃がすことがあります。そこで検索時には、候補を ef 個まで同時に抱えて探索を広げます。ef を大きくすれば取り逃がしは減りますが、距離の計算が増えて遅くなります。インデックスを作るときの1点あたりの辺の数(M)も、大きいほど精度が上がる代わりにメモリと構築時間を食います。HNSW 以外にも、空間をクラスタに分けて有望なクラスタだけを調べる IVF や、ベクトルを短い符号に量子化してメモリを節約する直積量子化(PQ)などがあり、実製品ではこれらを組み合わせます。どれも再現率(本当の近傍をどれだけ拾えるか)と、速度・メモリの取引で、インデックスのパラメータ調整はこの釣り合いを取る作業です。
下の部品で確かめてください。点の雲の上でクエリ(◇)をドラッグすると、HNSW が上の層から跳んで近傍に着くまでの経路と、距離を計算した回数が出ます。全件走査と比べて何回で済むか、そして真の最近傍(緑の輪)をときどき外すことを見てください。
◇(クエリ)をドラッグして離してください。HNSW が上の層の入口から跳んで近傍に着くまでの道と、距離を計算した回数が出ます。
従来のデータベースとの違いと共通点
RDBMS のインデックスが「完全一致・範囲・並び順」を速くする装置だとすれば、ANN のインデックスは「距離の近さ」を速くする装置で、答えが近似になる点が本質的に違います。一方で、データベースとしての要求は共通です。実務の検索は「意味が近く、かつ種類が契約書で、作成日が今年」のようにメタデータでの絞り込みを伴います。先に絞り込むとグラフがまばらになって HNSW がうまく進めず、後で絞り込むと上位 k 件がほとんど条件に合わず捨てられる、というジレンマがあり、両者をうまく組み合わせられるかが製品の差になります。さらに、HNSW はグラフの形そのものが索引なので、大量の削除や更新はグラフを傷め、再構築が必要になることがあります。大量のデータではシャーディングやレプリケーションによるスケーリングも必要になり、このあたりの設計は NoSQL の系譜に連なります。
専用 DB か、既存 DB の拡張か
選択肢は大きく2つあります。Pinecone・Milvus・Qdrant のような専用のベクトルデータベースは、ANN 検索に最適化された性能・スケール・運用機能を持ちます。その代わり、システムの部品が1つ増え、既存データとの同期(商品情報は RDBMS に、ベクトルは専用 DB に置いたとき、両者をどう一致させ続けるか)という古典的な悩みを抱え込みます。
対して pgvector(PostgreSQL 拡張)や、Elasticsearch・Redis・主要な NoSQL のベクトル検索機能のような既存 DB の拡張は、使い慣れた SQL とトランザクションの世界にベクトルの列を1つ足すだけで済み、同期の問題が消えます。数百万件規模までなら pgvector で十分実用的、というのがいまの相場観です。迷ったら「まず既存 DB の拡張で始め、規模や性能の要件が専用 DB を正当化するまで移行しない」のが堅実で、これはマイクロサービスを最初から選ばない判断と同じ形の取引です。
RAG の検索基盤として
ベクトルデータベースの位置づけが最もよく分かるのが RAG のパイプラインです。事前に文書を分割して埋め込みに変えて格納しておき、質問のたびに近傍検索で関連する文書を取り出して、大規模言語モデル(LLM)のプロンプトに添えます。
この構成での典型的な落とし穴は、検索品質の問題をすべてベクトルデータベースのせいにしてしまうことです。実際には、チャンク分割の粒度、埋め込みモデルが領域に合っているか、キーワード検索(全文検索)と組み合わせるハイブリッド検索や、上位の候補を並べ直す再ランキングの有無が、精度を大きく左右します。型番や固有名詞のように「字面が一致すること」が大事な検索では、意味の近さよりキーワード検索のほうが強いことも少なくありません。ベクトルデータベースはあくまで「近いベクトルを速く返す」係で、「何を近いとみなすか」は埋め込みの側の責任です。この分担を押さえておくと、RAG の改善点を正しく切り分けられます。
試問
ベクトルデータベースは、文章や画像を「意味が近いものほど近くに来る点」に変え、問い合わせの点に近い順に探します。いっぽう普通のデータベースは、番号や値が条件に一致するかで探します。下の7つの探しものが、どちらに向いているかを考えます。
7つの探しものを、意味の近さで探すベクトル検索に向くものと、条件の一致で探す普通の検索に向くものに仕分けよ
項目を選んでから、入れる箱を選びます
