最近、RAG(検索拡張生成)の実装でベクトル検索が必要になる場面が増えてきました。PostgreSQLのpgvectorやPineconeのような専用サービスを使うのが王道ですが、「もっと軽量に始めたい」「サーバーレスで動かしたい」というケースも結構あるんですよね。

そこで注目したいのが、SQLiteでのベクトル検索です。特にハミング距離を活用したハイブリッド検索アプローチが、Hacker Newsでも話題になっていたので詳しく調べてみました。

SQLiteでベクトル検索が注目される背景

SQLiteは世界で最も広く使われているデータベースエンジンです。サーバーが不要で、単一ファイルで完結するシンプルさが特徴ですね。スマートフォンアプリやElectronアプリ、エッジデバイスなど、あらゆる場所で動いています。

一方で、ベクトル検索はこれまでSQLiteの守備範囲外でした。しかし、sqlite-vecという拡張モジュールの登場で状況が変わりつつあります。

ベクトル検索の基本的な仕組み

ベクトル検索を簡単に説明すると、テキストや画像を数値のベクトル(埋め込みベクトル)に変換して、そのベクトル同士の「近さ」で類似度を測る手法です。

たとえば「猫が好きです」と「ネコが大好き」は文字列としては異なりますが、ベクトル空間では非常に近い位置にマッピングされます。この性質を利用して、意味的に近い文書を検索できるわけです。

ハミング距離とは何か

ハミング距離は、2つのバイナリ列(0と1の並び)を比較して、異なるビットの数を数える距離指標です。例えば「10110」と「10011」のハミング距離は3(3箇所が異なる)になります。

なぜこれがベクトル検索で役立つのかというと、バイナリ量子化という手法と組み合わせることで、高速な近似検索が可能になるからです。浮動小数点のベクトルを0/1のバイナリに変換すると、データサイズが大幅に削減されて、ハミング距離の計算はビット演算で超高速に実行できます。

ハイブリッド検索の実装方法

ハイブリッド検索とは、ベクトル検索(セマンティック検索)と従来のキーワード検索(BM25など)を組み合わせる手法です。どちらか一方だけよりも検索精度が向上するケースが多いとされています。

ステップ1:FTS5でキーワード検索を準備

SQLiteには標準でFTS5(Full-Text Search 5)モジュールが組み込まれています。これを使えばBM25ランキング付きの全文検索が簡単に実装できます。

CREATE VIRTUAL TABLE docs_fts USING fts5(title, body);
-- 検索
SELECT *, rank FROM docs_fts WHERE docs_fts MATCH 'SQLite ベクトル' ORDER BY rank;

ステップ2:sqlite-vecでベクトル検索を追加

sqlite-vec拡張を使えば、ベクトルデータの保存と類似検索が可能になります。バイナリ量子化にも対応していて、ハミング距離での検索がネイティブにサポートされています。

CREATE VIRTUAL TABLE docs_vec USING vec0(
  embedding bit[1024]  -- バイナリ量子化済みベクトル
);
-- ハミング距離で類似検索
SELECT rowid, distance FROM docs_vec
WHERE embedding MATCH ?
ORDER BY distance LIMIT 20;

ステップ3:スコアの統合

キーワード検索のBM25スコアとベクトル検索のハミング距離スコアを統合する方法として、Reciprocal Rank Fusion(RRF)がシンプルかつ効果的です。

-- RRFスコア = 1/(k + rank_keyword) + 1/(k + rank_vector)
-- k=60が一般的な設定値

このアプローチなら、「SQLiteとは」のような明確なキーワードクエリにも、「軽量で高速なデータベースを探している」のような意味的なクエリにも対応できます。

パフォーマンスの実力

ハミング距離検索の最大のメリットは速度です。浮動小数点のコサイン類似度と比較すると、バイナリ量子化+ハミング距離は約10〜30倍高速に動作するケースがあります。精度は若干落ちるものの、100万件規模のデータセットでも数十ミリ秒で結果が返ってくるレベルです。

メモリ使用量も劇的に削減されます。1024次元のfloat32ベクトルが4KBなのに対して、バイナリ量子化後はわずか128バイトです。PostgreSQLのような本格的なRDBMSが不要な小規模プロジェクトにとって大きなアドバンテージですね。

どんな場面で使えるか

SQLiteでのハイブリッド検索が特に有効なシーンをいくつか挙げてみます。

ローカルRAGアプリは最有力の活用先です。個人のドキュメントをベクトル化してローカルで検索する仕組みを、サーバーなしで構築できます。RAGの実装にSQLiteを使うことで、デプロイの複雑さが大幅に下がります。

また、モバイルアプリやElectronアプリでの検索機能にも向いています。外部のAPIに依存せずにオフラインで動作するのは、ユーザー体験として大きな差別化ポイントになりますね。

注意点と限界

もちろん万能ではありません。数百万件を超えるような大規模データセットでは、専用のベクトルデータベース(Zvecなど)を使う方が適切です。SQLiteの強みは軽量さとシンプルさなので、そこを活かせる規模感で使うのがベストだと感じました。

バイナリ量子化による精度の低下も考慮すべきポイントです。リランキングと組み合わせることで精度を補完する手法が一般的ですが、そのぶん実装の複雑さは増します。

まとめ

SQLiteでのベクトル検索は、sqlite-vec拡張とハミング距離の組み合わせで実用的なレベルに達しています。FTS5との統合によるハイブリッド検索は、小〜中規模のプロジェクトであれば専用のベクトルDBを導入するよりも遥かにシンプルに始められます。

特にローカルRAGやオフラインアプリでの活用を考えている方は、試してみる価値があると思います。

参考リンク