Litmus — 話題のニュースを、深く読み解く。 RSS
ソフトウェア

SQLite本体がベクトル検索拡張vec1の開発を始めた

SQLiteプロジェクト自身が2026年9月30日、ベクトル類似検索の拡張vec1を公式ソースツリーに取り込んだ。ビルドすれば今日からSQLの中でk近傍検索ができる、その仕組みと現在地を確かめた。

イメージ写真。色分けされた製本雑誌が奥まで並ぶ、見通しのいい図書館の書架の通路。

イメージ写真 記事の内容を撮影したものではありません。Photo by Gui Van-Gogh on Pexels

この記事には Amazon アソシエイトのリンクを含みます。

アプリのデータをSQLite1つにまとめているのに、「このメモに似た記録を探す」という機能だけは別のデータベースが要る。そんな状況に心当たりがあるなら、朗報がある。SQLiteプロジェクト自身が2026年9月30日、ベクトルの類似検索を行う拡張vec1を公式のソースツリーに取り込んだ。取り込みのコミットには「Import vec1 sources into directory ext/vec1/ of this project.」とある。ビルドすれば、今日から使える。どういう仕組みで動き、どこまで安心して使えるのかを確かめた。

SQLiteだけでは足りなかったこと

「似た文章を探す」機能を作ろうとすると、まず文章を数字の並びに変換する必要がある。文章をAIモデルに通すと、意味の近さを数百個の数字の並び(ベクトル)として表現できる。これを埋め込みベクトルと呼ぶ。似た意味の文章ほど、このベクトル同士の距離が近くなる。

ここで困るのが保存場所だ。これまでSQLiteの中には、ベクトル同士の距離を速く計算する仕組みが無かった。愚直に書けば全件のベクトルと距離を計算することになり、件数が増えるほど遅くなる。だから多くのアプリは、ベクトル専用の外部データベースを別に立てるか、有志が作ったサードパーティの拡張を組み込むしかなかった。asg017/sqlite-vecはその代表で、GitHubユーザーAlex Garcia氏(asg017)が個人で公開している実装だ。READMEには「sqlite-vec is a pre-v1, so expect breaking changes!」とあり、こちらもまだv1未満の段階にある。

つまり今までは、SQLite本体の機能ではなく、外部のプロジェクトに頼る選択肢しか無かった。ここに、SQLiteプロジェクト自身の実装が加わった。

vec1は何ができるのか

vec1は、SQLiteの仮想テーブルの仕組みを使った拡張だ。公式ページによれば、実装はCの単一ファイルvec1.cで、外部ライブラリへの依存がない。テーブルの作り方は次のようになる。

CREATE VIRTUAL TABLE tbl USING vec1(vector_column, metadata_column...);

vec1のリファレンスによると、ベクトルを入れる列は必ず1つ、それに加えて0〜255個のメタデータ列を持てる。検索はこの仮想テーブルに対するSELECTで行い、SELECT ... FROM tbl(VECTOR, PARAMETERS)という形を取る。PARAMETERSはJSONで、K(返す件数、0〜33554432)やnprobe(あとで触れる探索範囲の広さ)を指定する。距離はL2(ユークリッド距離)とコサイン距離に対応する。内積はまだ実装されておらず、公式ロードマップに次の課題として挙がっている。

仮想テーブルなので、検索結果を元のテーブルとJOINしたり、WHEREで絞り込んだりできる。ベクトルの計算だけ特別扱いで、残りは普段どおりのSQLで書ける。

ではここで疑問が浮かぶ。データの件数が増えても、この検索は遅くならないのだろうか。

全件を比較しなくていい理由

図書館で本を探すとき、全冊を1冊ずつ手に取って確認する人はいない。まずジャンルの棚を絞り、その中だけを見る。vec1が使うIVFADCという仕組みは、これと同じ発想になる。

IVFADC(Inverted File with Asymmetric Distance Computation)は、あらかじめ似たベクトルどうしをいくつかのグループ(クラスタ)にまとめておく。検索するときは、クエリのベクトルに近いクラスタだけを選び、その中だけを調べる。全部の棚を回らず、近そうな棚だけを見に行くイメージだ。

全件比較 全部を調べる IVFADC 近いクラスタだけ

図の丸がクエリ、灰色の点がベクトルだ。全件比較では太枠の矩形が平面全体を覆い、すべての点を検索範囲に含める。IVFADCでは1つのクラスタだけを円で囲み、そこだけを検索範囲にする。他の2つの塊(あわせて8個の点)は検索範囲の外に残る。データが増えてクラスタの外側の点が増えても、塗る面積(調べる件数)は増えにくい。これがデータ件数に対して検索が遅くなりにくい理由になる。

vec1はこのクラスタ分けに加えて、OPQ(Optimized Product Quantization、最適化積量子化)でベクトルを圧縮する。クラスタの数が増えても、1件ごとの保存と比較にかかるコストを抑える仕組みになる。先ほどのnprobeパラメータは、近いクラスタをいくつまで調べるかを指定する値で、小さくすれば速く、大きくすれば取りこぼしが減る。精度と速度のどちらを優先するかを、この1つの数値で調整できる。

SIMD命令にも対応しており、公式ページによるとx86ではAVX2、ARMではNEON(特別なコンパイルスイッチ不要)を使う。クラスタを絞ったうえで、1件ごとの距離計算そのものも速くする作りになっている。

では、この仕組みはもう安心して使えるのだろうか。

今すぐ使っていいか

答えは「ビルドすればすぐ試せるが、本番投入は慎重に」になる。

まだ開発中の0.8版

公式ページのロードマップは「1.0リリースに必要な追加機能は無い」としながら、同じ文の中で「ほぼすべての処理経路でテストが不十分」と明記している。バージョン番号も、公式ページの表示は「0.7」だが、2026年10月6日のコミットでvec1_info()が返す番号が「0.8」に上がった。ドキュメントの更新が、進んでいる開発に追いついていない。

もう1つの制約は配布形態だ。vec1は今のところ、SQLite本体の標準ビルド(sqlite3.c、amalgamationと呼ばれる1ファイル版)には含まれていない。使うには、ソースツリーからvec1.cを自分でビルドする必要がある。

ビルド方法は公式ページにそのまま書かれている。Linux/macOSならcc -g -O3 -DNDEBUG -mavx2 -mfma vec1.c -shared -fPIC -o vec1.so、Windows(MSVC)ならcl /Zi /O2 /DNDEBUG /arch:AVX2 vec1.c -link -dll -out:vec1.dllという具合だ。AVX2向けにビルドしたバイナリは、AVX2非対応のCPUでは動かない点も留意がいる。

取り込み後も続く開発

自分がこの話を追っていて驚いたのは、取り込まれて終わりではなく、今この瞬間も手が入り続けていることだ。公式リポジトリのコミット履歴を見ると、10月6日の番号更新のあとも、ほぼ連日のペースで修正が積まれている。

  • 10月7日: 権限まわりの修正
  • 10月9日: 壊れたデータの処理修正
  • 10月10日: 同じ日のうちに2件、クラスタ割り当ての丸め誤差の修正

コミットした人物(dan、SQLiteのFTS5なども手がけてきた開発者)の名前は毎回同じで、1人のペースで仕上げに向かっている様子がうかがえる。

要素の型が32ビット浮動小数点に限られる、パーティションキーに未対応、クエリのマルチスレッド化に未対応といった細かい制限も、公式ロードマップにはまだいくつも並ぶ。これらは今すぐの判断を左右するほどではないが、本番投入を考えるなら公式ページで最新のロードマップを確認したほうがいい。

まとめ

SQLiteプロジェクト自身が、ベクトルの類似検索を行う拡張vec1を2026年9月30日に公式ソースツリーへ取り込んだ。これまでサードパーティのsqlite-vecか外部のベクトルDBに頼るしかなかった選択肢に、本体プロジェクトが保守する実装が加わったことになる。仕組みの核はIVFADCとOPQで、クエリに近いクラスタだけを調べることでデータが増えても検索が遅くなりにくい。CREATE VIRTUAL TABLEで仮想テーブルを作り、既存のテーブルとJOINしながらSQLの中でk近傍検索を書ける。

バージョンは0.8で公式ロードマップ自身が「テスト不十分」と記す段階にあり、標準ビルドにもまだ入っていないため、本番で使うかどうかは公式ページの最新状況を見て判断する必要がある。

自分でビルドする手間さえかければ、サードパーティの拡張を探し回らなくても、SQLite本体と同じソースから類似検索を試せる。まずは手元の環境でビルドして、CREATE VIRTUAL TABLEから動かしてみるのが、この拡張の現在地を知る一番早い方法だ。

この記事の先を読む本を探す

特定の本を勧めるものではありません。検索結果から、いまの版と目次を確かめて選んでください。

コメント

気づきや感想をどうぞ

記事への補足や、読んで考えたことをお寄せください。個人情報や、他の人を傷つける内容の投稿はお控えください。

コメントを読み込んでいます…

    ほかの記事

    最新の記事 →