pgvector : ベクトル検索 PostgreSQL
pgvectorはPostgreSQLのオープンソース拡張機能で、制約の少ないPostgreSQLライセンスで提供されています。すでに管理しているデータベースにベクトルの保存と検索機能を追加し、最大2,000次元(半精度では4,000次元)の列にインデックスを作成できます。数十万個のチャンクからなるローカルのコーパスでは、運用するサービスを一つ減らせるうえ、SQLフィルターが機能し、リレーショナルデータとの同期を維持する必要もありません。
pgvectorはPostgreSQLの拡張機能で、すでに管理しているデータベースにベクトルの保存と検索の機能を追加します。ほとんどのローカル文書検索プロジェクトでは、稼働させるサービスと管理するバックアップをそれぞれ1つ減らせます。また、アクセス権による絞り込みも含め、SQLフィルターがきちんと機能します。このプロジェクトはPostgreSQLライセンスのもとで保守され、GitHubでホストされています。2026年9月末時点でスター数は23,000を超え、バージョンは0.8.6で、PostgreSQL 13以降に対応していました。
#採用する理由:サービスを追加せずに済む
ローカルの文書処理システムでは、すでにモデルサーバー、エンコーディング処理、文書ストレージが動いています。専用のベクトルデータベースを追加すると、コンテナ、ポート、バックアップがそれぞれ1つずつ増えます。さらに、文書を削除したときにリレーショナルデータとの同期がずれる可能性のある要素も1つ増えることになります。
PostgreSQL が既に存在する場合——業務アプリケーションではほぼ常にそうなります——pgvector はこの種の問題をすべて解消します。テキストのチャンクは、その出典であるドキュメントの隣にあるテーブルに格納され、外部キーによって整合性が保たれます。削除は期待通りに伝播し、別途クリーンアップタスクを作成したり監視したりする必要はありません。プロジェクトはまた、完全一致および近似検索、単一精度・半精度・バイナリ・スパースベクトル、5 種類の距離(L2、内積、コサイン、L1、ハミング、ジャカード)を追加し、PostgreSQL の ACID 準拠、時点復旧、結合を無料で継承します。
#実際にはどのように動作するか
あなたのドキュメント、あなたのAI:あなたのPDF、メモ、メールを扱う信頼性の高いローカルRAG。何もクラウドに送信しません。
- 永久に利用できるオンラインスペース
- PDF + ファイル
- 30日間返金対応
通常の列に加えて、ベクトルを格納する列を用意します。クエリは、質問のベクトルからの距離に基づいて行を並べ替え、最も近い行を返します。一般的な用途には3つの距離演算子で対応できますが、選ぶ演算子は埋め込みモデルの規約に合わせる必要があります。この不一致が、一見気付きにくい検索品質の低下を招く最もよくある原因です。長さが1に正規化されたベクトル(OpenAI および最近の埋め込みモデルの大半が該当)では、内積の計算が最も速く、コサイン類似度と同じ順位になります。
| 項目 | 概要 | 注目すべき点 |
|---|---|---|
| ベクトル列 | 次元数が固定された浮動小数点数の配列 | 次元数は埋め込みモデルによって決まり、変更するにはすべてを再エンコードする必要があります。 |
| 距離計算演算子 | コサイン、スカラー積、またはユークリッド(L2)距離 | モデルと一致している必要があります |
| HNSWインデックス | グラフインデックス、高速クエリ | 構築に時間がかかり、メモリ消費も多いものの、バージョン0.5以降では標準的な選択肢として妥当です |
| IVFFlatインデックス | 分割方式のインデックスで、構築コストが低い | 代表的なデータが揃ってから作成する |
| インデックスなし | すべての行を対象とする厳密なスキャン | 数万行程度までは十分に実用的 |
#開始に必要な最小SQL
- 01拡張機能を有効化CREATE EXTENSION IF NOT EXISTS vector; — 一度だけ実行する単一のコマンドです。
- 02列を追加ALTER TABLE chunks ADD COLUMN embedding vector(1024); — 次元数は、使用する埋め込みモデルの次元数と完全に一致する必要があります。
- 03インデックス化前にデータをロードするCOPYによる一括読み込みは、既存のインデックスがない方が高速です。代表的なデータ量に相当する行数が揃ってから、インデックスを作成してください。
- 04インデックスを作成CREATE INDEX CONCURRENTLY ON chunks USING hnsw (embedding vector_cosine_ops); — CONCURRENTLY オプションは、インデックス作成中に書き込みをブロッキングしないようにします。大きなテーブルでは長時間かかります。
- 05問い合わせるSELECT contenu FROM chunks WHERE document_id IN (SELECT id FROM documents WHERE utilisateur_autorise($1)) ORDER BY embedding <=> $2 LIMIT 5; — アクセス権限によるフィルタリングと類似度による並べ替えを、同じクエリで行います。
#次元数の制限を具体的に見る
pgvectorは4つの列型を定義しており、それぞれにインデックス付け可能な独自の次元上限があります。標準的なvector型(単一精度、要素あたり4バイト)は最大2,000次元までインデックス付け可能であり、これは一般的なオープンソースの埋め込みモデルの大部分(384次元から1,024次元)をカバーします。OpenAIのtext-embedding-3-largeのようにデフォルトで3,072次元というより広いモデルは、この上限を超えます。文書化された対策は、埋め込み生成時に次元を削減すること(APIで可能)か、halfvec型に切り替えることです。halfvecは半精度で保存し(要素あたり2バイト、容量は半分)、最大4,000次元までインデックス付け可能です。bit型(バイナリベクトル、ハミング距離またはジャカード距離)は最大64,000次元までインデックス付け可能であり、sparsevec(スパースベクトル)は最大1,000個の非ゼロ要素までインデックス付け可能です。これを超えると、PostgreSQLは列を依然として保存しますが(vector、halfvec、sparsevecは最大16,000次元まで)、インデックス付けはできず、完全なスキャンに頼ることになります。
#フィルタリングおよびアクセス権限
実際の質問がコーパス全体を対象とすることはまれです。求めているのは、特定のサービスに関する、特定の日付より後の記述で、しかもそのユーザーに閲覧権限がある文書内の箇所です。専用のベクトルデータベースでは、独自の構文や境界条件を持つメタデータフィルターでこれを指定します。PostgreSQLでは、類似度による並べ替えとともにWHERE句で指定し、必要に応じてユーザーテーブルと結合します。
プロジェクト自体が文書化している落とし穴があり、本番環境で遭遇する前に知っておくとよいでしょう。近似インデックス(HNSWまたはIVFFlat)では、フィルターはインデックスの走査前ではなく、走査後に適用されます。条件に合う行が全体の10%しかなく、hnsw.ef_searchがデフォルト値の40の場合、返されるのは平均4行だけで、要求した10行には届きません。公式の対策は、バージョン0.8.0から利用できる反復インデックス走査(SET hnsw.iterative_scan = strict_order)です。結果が不足したまま何の通知もなく返すのではなく、十分な数の結果が見つかるまで自動的に走査を再開します。
#どこまでが限界か
- 大規模メモリ
- 数百万のベクトルをフル精度で保存すると、多くの容量が必要になります。halfvecとバイナリ量子化で使用容量は減らせますが、専用エンジンは標準機能としてさらに高い圧縮率を実現します。これが最も明確な違いです。
- インデックスの構築時間
- 非常に大きなテーブルに対して HNSW インデックスを構築すると、時間がかかり、リソースを多く消費します。本番環境では、CREATE INDEX CONCURRENTLY を使用することで、インデックス作成中に書き込み操作をブロッキングせずに済みます。
- リソースの競合
- 負荷の重いベクトル検索をトランザクション処理と並行して行うと、両方の負荷が同じサーバーにかかります。読み取り専用レプリカも役立ちますが、役割を分離するほうがさらに効果的です。
- ベクトルの次元
- インデックスを作成できるベクトルの次元数には、型ごとに上限があります(vectorは2,000、halfvecは4,000)。一般的なモデルはこの範囲に収まりますが、次元数が非常に多いモデルでは、次元削減または量子化が必要です。
- ハイブリッド検索
- PostgreSQLは全文検索(tsvector)に対応しており、ベクトル距離と組み合わせることもできます。ただし、使い勝手を整えるのは利用者側の仕事です。単一のクエリでネイティブなハイブリッドスコアを取得するのではなく、2つのクエリを別々に実行してから、例えば相互順位融合(Reciprocal Rank Fusion)でランキングを統合する必要があります。
- 水平スケーリング
- 単一サーバーでは対応しきれない規模になると、文書化されている方法は、読み取り用のPostgreSQLレプリカや、CitusやPgDogのような分散ツールを利用することです。つまり、当初の主張とは逆に、追加の構成要素が必要になります。
#pgvectorまたは専用データベース
問うべきなのは、どちらが客観的に優れているかではなく、どちらが今の状況に合うかです。請求処理、アカウント、元の文書など、アプリケーションの正本となるデータをすでにPostgreSQLで管理しているなら、pgvectorが有利です。ベクトルの量やクエリの処理量が、アプリケーションの他の部分の性能を低下させずに単一のトランザクション処理サーバーで対応できる範囲を超える場合は、専用エンジンが有利です。また、純粋な性能上の理由よりも運用上の理由から、チームがAIコンポーネントを情報システムの他の部分から分離したい場合も、専用エンジンが有利です。
| 状況 | 選択 |
|---|---|
| PostgreSQLを導入済みで、チャンク数が数十万未満 | pgvectorで余裕を持って対応 |
| ベクトルとリレーショナルデータの整合性を保つ必要がある | pgvector:トランザクションは無料で提供されます |
| 既存の許可に基づく精密フィルタリング | pgvector |
| 4,000次元を超え、次元削減ができない埋め込みモデル | sparsevec 型、またはこの用途向けに設計された専用データベースを確認する |
| 数百万のベクトル、多数のクエリ | 専用エンジン(Qdrant、Milvus) |
| ノートブック内のプロトタイプ | どれでも構いません。後から変更できます |
- Qdrant:専用のベクトルデータベース
- データ量がpgvectorの処理能力を超える場合はMilvus
- FAISS:ベクトル検索の基盤となるライブラリ
- 完全なRAGチェーンを構築する
- 埋め込みモデルの選定
- QuelLLMローカルRAGキット:すべてのコンポーネントを1ページに
- 出典:GitHubの公式pgvectorリポジトリ
- 参照:pgvector のインデックスおよび型に関するドキュメント
- 出典:pgvectorのスケーリングガイド
#FAQ
pgvector は RAG に十分な速度を提供しますか?+
pgvector か Qdrant か?+
インデックスはHNSWとIVFFlatのどちらを選べばよいですか?+
メタデータでフィルタリングは可能ですか?+
埋め込みモデルを変更すると、どうなりますか?+
埋め込みモデルの次元が2000を超える場合、どうすればよいですか?+
遅いベクトルクエリを診断する方法は?+
ご意見、誤りのご指摘、補足はありますか?ぜひお知らせください。皆さんにとってより良いガイドにするために役立ちます。