pgvectorは、PostgreSQLにベクトル型と近傍検索を足すオープンソースの拡張機能です。埋め込み(embedding)を業務データと同じテーブルに保存し、SQLの ORDER BY ... LIMIT で「意味が近い行」を取り出せます。この記事では、2026年10月1日公開の最新版0.8.7を前提に、Windows・Ubuntu・Dockerそれぞれのインストール手順、距離演算子とインデックスの設定、WHERE句と組み合わせたときに結果が減る問題の直し方を、PostgreSQL 18.6上で実行した結果とあわせて説明します。
まとめ:pgvectorの要点と導入時の判断
- pgvectorはPostgreSQLの拡張で、拡張名は
vectorです。CREATE EXTENSION pgvector;は「not available」で失敗します。 - 最新版は0.8.7(2026-10-01)で、対応はPostgreSQL 13以降。版はSQLの
SELECT extversion FROM pg_extension WHERE extname = 'vector';で確認します。 - インストールはUbuntuなら
postgresql-18-pgvector、Windowsは公式のビルド済みバイナリが無くVisual Studioのnmakeでビルド、手早く試すならDockerのpgvector/pgvector:pg18-trixieです。 - 距離は
<=>がコサイン距離、<->がL2距離、<#>が負の内積。コサイン類似度は1 - (a <=> b)で求めますが、この式で並べ替えるとインデックスは使われません。 - インデックスはまずHNSW。
vector型でインデックスを張れるのは2,000次元までで、3,072次元の埋め込みはhalfvecに変換して張ります。 - HNSWにWHERE句を足すと、絞り込みはインデックス走査の後にかかるため件数が足りなくなります。0.8.0以降は
hnsw.iterative_scanで追加探索できますが、走査量やメモリの上限によっては必要件数に届きません。 - 業務データとの結合やトランザクションの一貫性が要るならpgvector。検索負荷が業務DBのCPUとメモリを常時圧迫する規模になったら専用ベクトルDBへの切り出しを検討します。
pgvectorとは:PostgreSQLにベクトル列と近傍検索を足す拡張
pgvectorは、PostgreSQLにベクトル用のデータ型・距離演算子・近似最近傍インデックス(HNSW/IVFFlat)を追加します。リポジトリは pgvector/pgvector で、ライセンスはPostgreSQL本体と同じPostgreSQL Licenseです。商用利用でもpgvector自体のライセンス料はかかりません。サーバーやマネージドサービスなどの利用費用は別途発生します。
専用のベクトルDBを別に立てる構成と違い、ベクトルは通常の列なので、トランザクション、JOIN、WAL経由のレプリケーション、ポイントインタイムリカバリがそのまま効きます。「商品テーブルの在庫ありの行だけを意味検索する」のように、業務データの条件と類似度を1本のSQLで書けるのが採用理由になります。ベクトル検索そのものの考え方はベクトル検索とセマンティック検索の違い:包含関係・仕組み・pgvectorでの実装と使い分けで整理しています。
拡張名はvector:CREATE EXTENSIONで間違えやすい点
製品名はpgvectorですが、OSにインストールされる拡張の名前は vector です。名前を取り違えると次のエラーになります(PostgreSQL 18.6・pgvector 0.8.7で実行)。
CREATE EXTENSION pgvector;
ERROR: extension "pgvector" is not available
HINT: The extension must first be installed on the system where PostgreSQL is running.
CREATE EXTENSION vector;
CREATE EXTENSION
HINTは「OSに未インストール」と読めますが、この例では拡張名の誤りが原因です。先に vector で試してください。CREATE EXTENSION vector; はデータベースごとに1回必要です。Azure Database for PostgreSQLの許可リスト(azure.extensions)に登録する名前も vector です。
使えるデータ型と次元の上限
pgvectorには4つの型があります。保存できる次元と、インデックスを張れる次元が別なので、埋め込みモデルの出力次元と突き合わせて型を選びます。
| 型 | 要素 | 保存できる上限 | HNSWの上限 | 1件のサイズ |
|---|---|---|---|---|
vector |
単精度(4バイト) | 16,000次元 | 2,000次元 | 4×次元+8バイト |
halfvec |
半精度(2バイト) | 16,000次元 | 4,000次元 | 2×次元+8バイト |
bit |
2値 | PostgreSQLのbit型に準拠 | 64,000次元 | 次元÷8+8バイト |
sparsevec |
疎ベクトル | 非ゼロ16,000要素 | 非ゼロ1,000要素 | 8×非ゼロ数+16バイト |
OpenAIの text-embedding-3-small(1,536次元)は vector のままHNSWを張れます。text-embedding-3-large(3,072次元)は保存はできてもインデックスで上限に当たります。対処は後述の「2,000次元を超える埋め込み」で扱います。埋め込みモデルの選び方は埋め込みモデルとは?仕組みと日本語モデルの選び方・RAG実装での判断基準【2026年版】を参照してください。
pgvectorのインストール手順:Windows・Ubuntu・Docker別
PostgreSQL本体が入っていることが前提です。本体の導入はPostgreSQLのインストール手順|Windows・Ubuntu別の導入とinitdbで決まる文字コードで扱っています。pgvectorは「PostgreSQLのメジャー版に合わせたパッケージ」を入れるのが原則で、版がずれると CREATE EXTENSION の段階で見つからないと言われます。
| 環境 | 手段 | コマンドの要点 |
|---|---|---|
| Ubuntu・Debian | PGDGのAPT | apt install postgresql-18-pgvector |
| RHEL系 | PGDGのYum | dnf install pgvector_18 |
| Windows | ソースからビルド | nmake /F Makefile.win |
| macOS | Homebrew・Postgres.app | brew install pgvector |
| どのOSでも | Docker | pgvector/pgvector:pg18-trixie |
| マネージド | 各クラウドの拡張機能 | CREATE EXTENSION vector; |
Ubuntu・DebianでのAPTインストール
Ubuntu標準のリポジトリではなく、PostgreSQL公式のAPTリポジトリ(PGDG)からパッケージを入れます。PGDGの設定後、サーバーのメジャー版番号を入れたパッケージ名で導入します。
# PGDGリポジトリを設定済みであること(https://wiki.postgresql.org/wiki/Apt)
sudo apt install postgresql-18-pgvector # 17系なら postgresql-17-pgvector
# 対象データベースで有効化
sudo -u postgres psql -d mydb -c "CREATE EXTENSION vector;"
パッケージ名の 18 は「動いているサーバーの版」です。クライアントの psql --version ではなく、サーバーで SHOW server_version; を確認してから選んでください。複数版を同居させている環境で取り違えが起きやすい箇所です。
Windowsでのビルドとよく出るエラー
pgvectorはWindows向けのビルド済みバイナリをGitHubで配布していません(リポジトリにはタグのみでリリース成果物が無い)。公式READMEが示すWindowsの導入方法は、Visual StudioのC++ビルドツールでのビルド、Docker、conda-forgeの3つです。ビルドは「x64 Native Tools Command Prompt for VS」を管理者として開いて実行します。
set "PGROOT=C:\Program Files\PostgreSQL\18"
cd %TEMP%
git clone --branch v0.8.7 https://github.com/pgvector/pgvector.git
cd pgvector
nmake /F Makefile.win
nmake /F Makefile.win install
公式READMEでは、Windowsでのビルド・インストール時のエラーとして次の4例を挙げています。公式READMEのInstallation Notesに対処が載っています。
| 出るメッセージ | 原因 | 対処 |
|---|---|---|
Cannot open include file: 'postgres.h' |
PGROOTの誤り | 実際の導入先と版番号に合わせる |
error C2196: case value '4' already used |
x64以外のプロンプトでビルド | x64 Native Toolsで開き直し、cleanして再実行 |
unresolved external symbol float_to_shortest_decimal_bufn |
PostgreSQL 17.0〜17.2 | 17.3以降へ上げる |
Access is denied |
権限不足 | 管理者としてプロンプトを開く |
ビルド環境を用意できない、あるいは開発機で試したいだけなら、WSL2上のUbuntuでAPTを使うか、次のDockerイメージを使う方が早く終わります。
Dockerイメージpgvector/pgvectorで起動
公式イメージ pgvector/pgvector は、PostgreSQL公式イメージにpgvectorを足したもので、起動方法は postgres イメージと同じです。タグは「PostgreSQLの版」と「Debianの版」の組み合わせで、0.8.7時点では pg13 から pg18 まで、trixie と bookworm が用意されています。
docker run -d --name pgv \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
--shm-size=1g \
pgvector/pgvector:0.8.7-pg18-trixie
docker exec -it pgv psql -U postgres -c "CREATE EXTENSION vector;"
pg18-trixie のような版なしタグは新しいpgvectorが出ると中身が替わります。本番や共有の開発環境では 0.8.7-pg18-trixie のように版を固定してください。--shm-size は、maintenance_work_mem を上げて並列でHNSWを作るときに共有メモリ不足のエラーを避けるための指定で、READMEは「maintenance_work_mem 以上」を求めています。
サーバーを立てずにブラウザやNode.jsの中だけで試す方法もあります。WebAssembly版PostgreSQLのPGliteで動かす手順はpgliteとpgvectorでDocker不要のローカル類似度検索を実装するにまとめています。
マネージドPostgreSQLの有効化手順と同梱バージョン
主要クラウドのPostgreSQLサービスはpgvectorを同梱しており、OSへのインストールは不要です。違いは有効化の前に必要な手順と、入っているpgvectorの版です。
| サービス | 有効化の前に必要なこと | 同梱版(2026年10月時点) |
|---|---|---|
| Amazon RDS for PostgreSQL | なし | 0.8.2(18.6・17.11・16.15) |
| Azure Database for PostgreSQL | azure.extensions に VECTOR を許可 |
0.8.2(13〜18) |
| Cloud SQL for PostgreSQL | なし | 0.8.5(13以降) |
| Supabase | ダッシュボードのExtensionsで vector を有効化 |
ダッシュボードで確認 |
同梱版は2026年10月6日に、AWSの拡張機能一覧、Microsoft Learnの拡張機能バージョン一覧、Google Cloudの拡張機能一覧で確認した値です。サービス側の更新で変わるので、利用前に接続先でも確認してください。
RDSとCloud SQLは、接続して CREATE EXTENSION vector; を実行すれば使えます。Azureは先にサーバーパラメーター azure.extensions の許可リストへ追加し、SHOW azure.extensions; で反映を確かめてから CREATE EXTENSION を実行します。Supabaseは create extension vector with schema extensions; のように extensions スキーマへ入れる流儀です。サービス自体の構成はAzure Database for PostgreSQLとは?フレキシブルサーバーの構成・ゾーン冗長HA・料金体系と移行判断を実装目線で解説などで扱っています。
マネージドで注意したいのは版です。上の表のとおり、RDSとAzureの同梱版は0.8.2で、最新の0.8.7より古いままです。0.8.3以降のHNSW関連の修正は、各サービスが同梱版を上げるまで入りません。SELECT extversion FROM pg_extension WHERE extname = 'vector'; で、接続先の実際の版を確かめてから設計してください。
インストール後の確認とアップデート
入ったかどうかは、OSに置かれた版(default_version)とデータベースで有効な版(installed_version)を並べて見ると一度で分かります。
SELECT name, default_version, installed_version
FROM pg_available_extensions WHERE name = 'vector';
name | default_version | installed_version
--------+-----------------+-------------------
vector | 0.8.7 | 0.8.7
パッケージを新しくしただけでは、既存データベースの拡張は古い版のままです。installed_version が古ければ、データベースごとに ALTER EXTENSION vector UPDATE; を実行します。0.8.3〜0.8.7はHNSWのVACUUM時のインデックス破損やIVFFlat構築時のバッファオーバーフローの修正を含むので、0.8.2以前を使っているなら更新を優先してください。
pgvectorの使い方:テーブル作成から近傍検索まで
最小の流れは「列を作る→ベクトルを入れる→距離演算子で並べ替える」の3手です。
CREATE TABLE items (id bigserial PRIMARY KEY, category_id int, embedding vector(3));
INSERT INTO items (category_id, embedding)
VALUES (1, '[1,2,3]'), (2, '[4,5,6]'), (1, '[1,1,0]');
-- [3,1,2] に近い順に5件
SELECT id FROM items ORDER BY embedding <=> '[3,1,2]' LIMIT 5;
列の次元は型で固定されます。vector(3) の列に2次元を入れると ERROR: expected 3 dimensions, not 2 で拒否されるので、埋め込みモデルを替えて次元が変わる場合は列ごと作り直す前提で設計してください。
距離演算子6種の意味と実際の値
上の3行に対して、問い合わせベクトル [3,1,2] との距離を各演算子で計算した結果です。
SELECT id,
embedding <-> '[3,1,2]' AS l2,
embedding <#> '[3,1,2]' AS neg_ip,
embedding <=> '[3,1,2]' AS cos_dist,
1 - (embedding <=> '[3,1,2]') AS cos_sim,
embedding <+> '[3,1,2]' AS l1
FROM items ORDER BY id;
id | l2 | neg_ip | cos_dist | cos_sim | l1
----+--------------------+--------+---------------------+--------------------+----
1 | 2.449489742783178 | -11 | 0.2142857142857143 | 0.7857142857142857 | 4
2 | 5.744562646538029 | -29 | 0.11673988938389968 | 0.8832601106161003 | 9
3 | 2.8284271247461903 | -4 | 0.2440710539815456 | 0.7559289460184544 | 4
L2距離では1が最も近いのに、コサイン距離では2が最も近くなります。L2はベクトルの長さの差も距離に入れ、コサインは向きだけを見るためです。どちらを使うかは埋め込みモデルの指定に従い、OpenAIの埋め込みのように長さ1へ正規化済みのベクトルなら、コサインと内積で順位は同じになります。
次の表の vector_* は vector 型用の演算子クラスです。halfvec 型では halfvec_*、sparsevec 型では sparsevec_* を使います。例えばコサイン距離なら、それぞれ halfvec_cosine_ops、sparsevec_cosine_ops です。
| 演算子 | 距離 | HNSWの演算子クラス | 対象の型 |
|---|---|---|---|
<-> |
L2(ユークリッド) | vector_l2_ops |
vector・halfvec・sparsevec |
<#> |
負の内積 | vector_ip_ops |
vector・halfvec・sparsevec |
<=> |
コサイン距離 | vector_cosine_ops |
vector・halfvec・sparsevec |
<+> |
L1(0.7.0から) | vector_l1_ops |
vector・halfvec・sparsevec |
<~> |
ハミング | bit_hamming_ops |
bit |
<%> |
ジャッカード | bit_jaccard_ops |
bit |
<#> が負の値を返すのは、インデックスを使った並べ替えが距離演算子の昇順にしか対応しないためで、内積が大きいほど小さい値になるよう符号を反転しています。内積そのものが欲しければ -1 を掛けます。コサイン類似度の式と意味はコサイン類似度とは?計算式・仕組みと類似検索での実装を実装目線で解説で詳しく扱っています。
コサイン距離のORDER BYとインデックス利用条件
pgvectorのインデックスが使われる条件は、ORDER BY に距離演算子をそのまま書き、昇順で、LIMIT があることです。類似度に変換した式で降順に並べると、HNSWがあっても全件走査になります。10万件・16次元のテーブルにHNSWを張り、両方の書き方で実行計画を取りました。以降の検証は次の docs テーブルで行っています。実行計画や近似検索の返却件数は、環境とインデックスの構築結果で変わります。
CREATE TABLE docs (id bigserial PRIMARY KEY, category_id int, embedding vector(16));
SELECT setseed(0.42);
INSERT INTO docs (category_id, embedding)
SELECT (g % 100),
(SELECT array_agg(random())::vector(16) FROM generate_series(1, 16) WHERE g > 0)
FROM generate_series(1, 100000) g; -- category_id は0〜99が各1,000件
CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops);
ANALYZE docs;
-- 距離演算子のまま昇順:インデックスを使う
EXPLAIN (COSTS OFF) SELECT id FROM docs
ORDER BY embedding <=> '[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]' LIMIT 5;
Limit
-> Index Scan using docs_embedding_idx on docs
Order By: (embedding <=> '[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]'::vector)
-- 類似度に変換して降順:全件走査になる
EXPLAIN (COSTS OFF) SELECT id FROM docs
ORDER BY 1 - (embedding <=> '[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]') DESC LIMIT 5;
Limit
-> Gather Merge
-> Sort
-> Parallel Seq Scan on docs
類似度を画面に出したいときは、並べ替えは距離演算子で行い、SELECT 句で 1 - (embedding <=> ...) を計算して返します。
HNSWとIVFFlatのインデックス設計
近似最近傍インデックスを使わない検索は、検索対象の各ベクトルとの距離を計算する厳密最近傍検索で、再現率は100%ですが件数に比例して遅くなります。近似最近傍のインデックスを張ると、再現率と引き換えに速くなり、同じクエリでも返る行が変わることがあります。2種類の性質は次のとおりです。
| 項目 | HNSW | IVFFlat |
|---|---|---|
| 速度と再現率の釣り合い | 良い | HNSWより劣る |
| 構築時間・メモリ | 遅い・多い | 速い・少ない |
| データ投入前の作成 | できる | データ投入後に作る |
| 構築時の設定 | m(16)、ef_construction(64) |
lists |
| 検索時の設定 | hnsw.ef_search(40) |
ivfflat.probes(1) |
括弧内は既定値です。迷ったらHNSWを選びます。IVFFlatは、HNSWの構築時間やメモリ消費が制約になる場合の候補です。実データで再現率と検索時間を比較して選びます。アルゴリズムの内部はHNSWとは?階層グラフの仕組みとM・ef_constructionの決め方を実装目線で解説【2026年版】、近似最近傍探索の全体像は近似最近傍探索とは?HNSW・IVF・PQの選び分けとRecall調整を実装目線で解説【2026年版】で解説しています。
HNSWの作成とef_searchの調整
演算子クラスは検索で使う距離に合わせます。コサイン距離で検索するのに vector_l2_ops で作ると、そのインデックスは使われません。
CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- 再現率を上げたいクエリだけ探索幅を広げる
BEGIN;
SET LOCAL hnsw.ef_search = 100;
SELECT id FROM docs
ORDER BY embedding <=> '[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]' LIMIT 10;
COMMIT;
構築はグラフが maintenance_work_mem に収まるかで速度が大きく変わります。既定の64MBのまま10万件・16次元で作ったところ、NOTICE: hnsw graph no longer fits into maintenance_work_mem after 84325 tuples が出ました。このNOTICEは構築失敗を意味しません。構築時間の短縮が必要で、利用可能なメモリに余裕がある場合は、次回の構築時にセッションだけ SET maintenance_work_mem = '2GB'; のように上げてから作り直します。できたインデックスは35MBで、元のテーブル(11MB)の3倍強でした。HNSWはメモリに載っている前提で速いので、本番のメモリ見積もりにはインデックスのサイズを入れてください。
IVFFlatのlistsとprobesの決め方
IVFFlatはベクトルを lists 個のグループに分け、問い合わせに近い probes 個のグループだけを調べます。READMEの目安は、lists が100万行までは「行数÷1000」、それを超えたら「行数の平方根」、probes は「lists の平方根」です。
-- 50万行なら lists = 500、probes = 22 前後から調整
CREATE INDEX ON docs USING ivfflat (embedding vector_cosine_ops) WITH (lists = 500);
SET ivfflat.probes = 22;
IVFFlatはデータからグループの中心を学習するため、空や少量のテーブルで作ると精度が出ません。データ投入後に作り、件数が大きく増えたら作り直します。
2,000次元超の埋め込みとhalfvec式インデックス
text-embedding-3-large の3,072次元を vector 列に入れてHNSWを作ると、次のエラーで止まります。列はそのままに、式インデックスで半精度に変換すれば4,000次元まで張れます。ただし半精度化で値が丸められるため、検索品質を比較し、必要なら候補を多めに取得して元のベクトルで並べ直します。
CREATE TABLE big (id bigserial PRIMARY KEY, embedding vector(3072));
CREATE INDEX ON big USING hnsw (embedding vector_cosine_ops);
ERROR: column cannot have more than 2000 dimensions for hnsw index
CREATE INDEX ON big USING hnsw ((embedding::halfvec(3072)) halfvec_cosine_ops);
CREATE INDEX
-- 検索側も同じ式で書く(式が一致しないとインデックスは使われない)
-- array_fill は構文確認用。実際は同じ埋め込みモデルで作った問い合わせベクトルを渡す
SELECT id FROM big
ORDER BY embedding::halfvec(3072)
<=> array_fill(1::real, ARRAY[3072])::halfvec(3072) LIMIT 10;
4,000次元も超えるなら、binary_quantize() で bit 型にしてハミング距離で候補を多めに取り、元のベクトルで並べ直す方法がREADMEに載っています。次元削減に対応した埋め込みモデルなら、出力次元を1,536などに指定して vector のまま扱うのが最も単純です。
WHERE句で結果が減る問題と反復インデックススキャン
HNSWを張った後に起きやすいのが、「条件付き検索の件数が LIMIT に届かない」現象です。近似インデックスでは、WHERE句の絞り込みはインデックス走査の後にかかります。HNSWが一度に返す候補は hnsw.ef_search の40件なので、条件に合う行が全体の10%なら平均4件しか残りません。
10万件のうち category_id = 7 が1%(1,000件)のテーブルで、上位10件を求めた結果です。
SELECT count(*) FROM (
SELECT id FROM docs WHERE category_id = 7
ORDER BY embedding <=> (SELECT embedding FROM docs WHERE id = 1) LIMIT 10
) s;
-- 既定(反復スキャンなし)
count
-------
0
SET hnsw.iterative_scan = strict_order;
-- 同じクエリを再実行
count
-------
10
条件に合う行が1,000件あるのに、既定では0件でした。反復インデックススキャン(0.8.0で追加)を有効にすると、足りない分だけインデックスを追加で走査し、10件が返ります。strict_order は距離順を厳密に守り、relaxed_order は多少の順序の乱れを許す代わりに再現率が上がります。IVFFlatは relaxed_order だけで、strict_order を指定すると ERROR: invalid value for parameter "ivfflat.iterative_scan" になります。
反復スキャンは走査量に上限があり、HNSWは hnsw.max_scan_tuples(既定20,000)を目安に追加走査を制限します。この値は厳密な上限ではなく、初回走査には適用されません。条件に合う行がごく少ない場合や、反復スキャンを使えない版では、インデックスの側で対処します。同じテーブルで3つの方法を試した結果です。
| 方法 | 実行計画 | 返った件数 |
|---|---|---|
| 何もしない | HNSW+後段のFilter | 0件 |
category_id にB-treeを追加 |
HNSW+後段のFilter(変わらず) | 0件 |
WHERE (category_id = 7) 付きの部分HNSW |
部分インデックスを走査 | 10件 |
READMEは「まず絞り込み列にインデックスを」と勧めていますが、この条件ではプランナーがHNSWを選び続け、B-treeは使われませんでした。B-treeを足したら EXPLAIN で Filter: が残っていないか必ず確かめてください。値の種類が少ない列なら部分インデックスを値ごとに作るのが確実で、テナントごとに分けたい場合は PARTITION BY LIST でパーティションを切ります。READMEも、テナント間でインデックスを共有すると他テナントのベクトルが再現率と速度に影響するとして、パーティションか別テーブルを勧めています。
手元の版やマネージドの同梱版が0.8.0より古い場合(RDSのPostgreSQL 12系は0.7.3止まり)、反復スキャンは使えません。その場合は hnsw.ef_search を上げるか、部分インデックスやパーティションを検討します。絞り込み列のB-treeを使う場合は、実行計画と返却件数を確認してください。
pgvectorと専用ベクトルDB・Faissの選び分け
比較でよく並ぶFaissはMetaのライブラリで、データベースではありません。索引の保存・読み込みなどの機能はありますが、権限管理や障害復旧を含むデータベースとしての運用機構はアプリ側で設計する必要があります。PineconeやMilvusのような専用DBは、それらを持ったうえでベクトル検索に特化した製品です。pgvectorを選ぶか外に出すかは、次の条件で判断します。
| 条件 | 向く選択 |
|---|---|
| 既にPostgreSQLで業務データを持っている | pgvector |
| 類似度と業務条件・JOINを1本のSQLで書きたい | pgvector |
| ベクトルと元データの整合をトランザクションで保ちたい | pgvector |
| 数億件以上を常時高QPSで検索する | 専用ベクトルDB |
| 検索負荷を業務DBから切り離したい | 専用ベクトルDB |
| バッチで作った索引をメモリ上で速く引くだけ | Faiss |
判断を誤りやすいのは、ベクトルを「件数が多いから」と最初から専用DBに分ける構成です。元データとベクトルの二重管理が生まれ、削除や権限変更の反映漏れが検索結果に出ます。PostgreSQLの非パーティションテーブルは既定で32TBまで入ります。HNSWのインデックスがメモリに載る範囲であれば、まずpgvectorで始めて、負荷が業務DBに響いてから切り出しを検討する順番で十分です。逆に、検索が業務DBのCPUとメモリを常時圧迫する規模では、pgvectorに固執せず分けるべきです。製品ごとの比較はベクトルデータベースとは?ベクトル化・インデックス構造・製品比較【2026年版】にまとめています。
DifyのベクトルストアをpgvectorにするDocker設定
LLMアプリ基盤のDifyは、セルフホスト版のベクトルストアとしてpgvectorを選べます。既定はWeaviateで、最新の1.17.1(2026-09-10)のDocker構成では、docker ディレクトリの .env で次を変えるだけで切り替わります。
# docker/.env
VECTOR_STORE=pgvector
# 接続先(既定値。compose内のpgvectorコンテナを指す)
PGVECTOR_HOST=pgvector
PGVECTOR_PORT=5432
PGVECTOR_USER=postgres
PGVECTOR_PASSWORD=difyai123456
PGVECTOR_DATABASE=dify
# 同梱コンテナの初期化用(接続用と同じ値にそろえる)
PGVECTOR_POSTGRES_PASSWORD=difyai123456
COMPOSE_PROFILES が VECTOR_STORE の値を参照するため、docker compose up -d で pgvector/pgvector:pg16 のコンテナが代わりに起動します。既定のパスワード difyai123456 は公開リポジトリに載っている値なので、本番環境では変更してください。同梱コンテナを新規初期化する場合は、接続用の PGVECTOR_PASSWORD とサーバー初期化用の PGVECTOR_POSTGRES_PASSWORD に同じ値を設定します。初期化済みのDBでは環境変数の変更だけではDB側のパスワードは変わりません。既存のRDSやAzureのPostgreSQLを使う場合は、PGVECTOR_HOST などをそちらに向け、接続先のデータベースで CREATE EXTENSION vector; を済ませておきます。同梱のpgvectorコンテナでは、PGVECTOR_PG_BIGM=true により起動スクリプトがpg_bigmを導入します。外部のRDSやAzureにこの設定でpg_bigmをインストールすることはできないため、接続先サービスの対応状況と有効化手順を別途確認してください。
VECTOR_STORE を替えても、作成済みナレッジの索引は自動では移りません。運用中に切り替えるなら、apiコンテナで flask vdb-migrate を実行して索引を新しいストアに作り直します。埋め込みの再計算が走るので、ナレッジが大きい場合はAPI費用と時間を見込んでください。
よくある質問
pgvectorとは何ですか?
PostgreSQLにベクトル型と距離演算子、HNSW・IVFFlatの近似最近傍インデックスを追加するオープンソースの拡張機能です。埋め込みを業務データと同じテーブルに置き、SQLで類似検索できます。ライセンスはPostgreSQL Licenseで無料です。
WindowsでPgvectorをインストールするにはどうすればいいですか?
公式のビルド済みバイナリは無いため、Visual StudioのC++ビルドツールを入れ、「x64 Native Tools Command Prompt」を管理者で開いて PGROOT を設定し、nmake /F Makefile.win と nmake /F Makefile.win install を実行します。ビルド環境を用意できない場合はDockerかWSL2のUbuntuを使います。
CREATE EXTENSION pgvectorがエラーになるのはなぜですか?
拡張の名前が vector だからです。CREATE EXTENSION vector; と書きます。vector でも「not available」になる場合は、拡張自体が未導入か、別のPostgreSQL環境にインストールされている可能性があります。SHOW server_version; でサーバーの版を確かめ、同じ版のパッケージが入っているかを確認してください。
pgvectorのバージョンを確認する方法は?
データベースで有効な版は SELECT extversion FROM pg_extension WHERE extname = 'vector'; で確認します。OSに入っている版と比べるなら pg_available_extensions の default_version を見ます。2026年10月時点の最新は0.8.7です。
pgvectorでハイブリッド検索はできますか?
できます。PostgreSQLの全文検索(tsvector)やpg_bigmで取ったキーワード検索の結果と、pgvectorの近傍検索の結果を、Reciprocal Rank Fusionなどで1つの順位にまとめます。pgvector単体にハイブリッド検索の関数は無く、2つのクエリを組み合わせる形になります。