👋

Dockerでpgvectorを導入|既存PostgreSQLをRAG対応ベクトルDBに拡張する手順

に公開

はじめに

RAG構築でpgvectorが採用される理由

「RAGを導入したいけれど、どのベクトルDBを選べばいいのか分からない」そんな声を多く聞くようになりました。生成AIの普及により、企業でもRAG構築が急速に進んでいます。

中でも、PostgreSQLの拡張機能であるpgvectorは、多くの現場で採用が進むベクトルDBとなっています。

理由はシンプルで、既存のRDS(PostgreSQL)環境と自然に統合できる点です。
新しい専用DBを増やさず、既存の業務システムにベクトル検索を組み込めます。
SQLベースで扱えるため、開発・運用チームでも導入しやすく、コストを抑えつつ柔軟に拡張できます。

PineconeやFaiss、AWSのOpenSearchやKendra、AzureのAI Searchなど、さまざまな構成が存在しますが、PostgreSQLは企業での導入実績が豊富なため、「まずは試してみたい」「自社のRDS環境を活かしたい」というケースで特に選ばれやすいと感じています。

Pinecone / Faiss / OpenSearch / Kendra / AI Searchとの立ち位置比較

それぞれのベクトルDBには得意分野があります。
目的に応じて選択肢を変えることで、より効率的にRAGを構築できます。

ユースケース おすすめDB 特徴
まずはPoCで検証したい Pinecone APIで手軽に使え、embeddingモデルの比較にも最適
高速な類似検索を重視したい Faiss C++実装で非常に高速、ローカル向けの軽量選択肢
インフラを意識せずに使いたい OpenSearch / Kendra / AI Search フルマネージドでスケールしやすく、AWS/Azureとの親和性が高い
既存のPostgreSQL資産を活かしたい pgvector RDSに拡張導入でき、通常DBと統合して運用可能

こうして見ると、pgvectorは「既存環境を活かしつつベクトル検索を導入したい企業」にとって、最もバランスの取れた選択肢と言えるでしょう。

実務で3現場連続採用されている背景

私自身、これまで3つの現場でRAG構築を担当してきましたが、すべてpgvectorが採用されていました。
その理由として大きかったのは、以下の3点です。

  1. 既存のPostgreSQLに拡張導入できるため、新しいDB基盤を増やさずに済む
  2. コストを抑えてRAGを構築できる(Pineconeなどの従量課金に比べて安価)
  3. DB運用の一元化が可能で、監視やバックアップも既存の仕組みを活かせる

結果として、開発・運用両面での安心感が高く、RAGの実装を素早く進められる点が評価されています。
これらの経験からも、pgvectorは今後さらに採用が増えると感じています。特に、RAGの商用実装が増える中で「既存DBと共存できる」点は今後ますます重要になっていくでしょう。

Dockerでpgvector環境を構築

Docker Composeでpgvectorが入っていないPostgreSQLを立ち上げる

まずはDocker Composeで、pgvectorなしのPostgreSQLを立ち上げます。

docker-compose.yml(pgvectorなし)

services:
  postgres:
    image: postgres:16
    container_name: postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret-password
      POSTGRES_DB: appdb
      TZ: Asia/Tokyo
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Dockerを立ち上げた状態で、上記のファイルを現在のディレクトリに配置し、下記を実行。

# 起動
docker compose up -d

# 動作確認(psql で接続)
docker exec -it postgres psql -U app -d appdb

ここまでで、PostgreSQLコンテナへの接続確認が完了です。

pg_available_extensionsで利用可能か確認

ログイン状況で下記を確認し、利用できない状態なので、0行が返ってくればOK。

SELECT name, default_version, installed_version FROM pg_available_extensions WHERE name='vector';

※「postgres:16」ではpgvectorが利用できないので、「pgvector/pgvector:pg16」に切り替える必要がある。
※移行前にまずはDBのバックアップを取っておく。

docker exec -i postgres pg_dump -U app -d appdb > backup_$(date +%Y%m%d%H%M%S).sql

※現在のディレクトリにSQLファイルが保存されている。

Docker Composeのイメージの変更。以下に差し替え

services:
  postgres:
    image: pgvector/pgvector:pg16 #ここが変わった。
    container_name: postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret-password
      POSTGRES_DB: appdb
      TZ: Asia/Tokyo
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

※下記公式HPに、「マイナーリリースは内部ストレージ形式を変更することはなく、同じメジャーバージョン番号の以前のマイナーリリースと常に互換性があります。」と記載あり。

PostgreSQL公式ドキュメント - Upgrading a PostgreSQL Cluster

入れ替え起動を実施する

# イメージをpull
docker compose pull
# 起動
docker compose up -d
# 起動確認
docker compose logs -f postgres | sed -n '1,120p'
# 以下のログが出ていればOK
## database system is ready to accept connections

コンテナ内でCREATE EXTENSION vector;を実行

再度DBに接続する

# 動作確認(psql で接続)
docker exec -it postgres psql -U app -d appdb

# vectorが使えるようになっているので1行レコードが返る。
SELECT name, default_version, installed_version FROM pg_available_extensions WHERE name='vector';

# vectorを使えるようにする。
CREATE EXTENSION vector;

サンプルデータ登録とベクトル検索を試す

まずはベクトルDBを作成する。

CREATE TABLE docs (
  id SERIAL PRIMARY KEY,
  title TEXT NOT NULL,
  category TEXT,
  embedding VECTOR(3) -- 次元数は、各埋め込みモデルの次元数によって変化させる。
);

ダミーデータの作成

INSERT INTO docs (title, category, embedding) VALUES
  ('社内規程の改定',        'policy',   '[0.9, 0.1, 0.0]'),
  ('有給申請の手順',        'policy',   '[0.85, 0.05, 0.05]'),
  ('請求書のテンプレート',  'finance',  '[0.1, 0.9, 0.1]'),
  ('経費精算のルール',      'finance',  '[0.1, 0.85, 0.15]'),
  ('VPN接続トラブル対応',   'it',       '[0.05, 0.05, 0.95]'),
  ('PCセットアップ手順',    'it',       '[0.1, 0.1, 0.9]');

検索の実施

WITH q AS (SELECT '[0.95,0.05,0.0]'::vector AS v)
SELECT id, title, category, embedding <=> (SELECT v FROM q) AS cosine_dist
FROM docs
ORDER BY embedding <=> (SELECT v FROM q)
LIMIT 3;

カテゴリで絞って検索

WITH q AS (SELECT '[0.95,0.05,0.0]'::vector AS v)
SELECT
  id,
  title,
  category,
  embedding <=> (SELECT v FROM q) AS cosine_dist
FROM docs
WHERE category = 'policy'
ORDER BY embedding <=> (SELECT v FROM q)
LIMIT 3;

ベクトル検索がどう動くかを体感

pgvectorでは、ベクトル同士の「距離(類似度)」を計算することで、
テキストやドキュメント間の意味的な近さを求めます。

今回の例では、演算子 <=> を使って cosine距離(cosine distance) を計算しています。
距離が小さいほど、クエリベクトルに“意味的に近い”データと判断されます。

このようにpgvectorでは、SQLだけで「意味的に近い文書検索」を実現できます。
RAG構築では、ここで取得した上位文書をLLMに渡すことで、より文脈に沿った回答生成が可能になります。

RAG連携の比較

コスト・運用・速度比較表

RAG構築では、どのベクトルDBを使うかによって運用コストや速度が大きく変わります。
ここでは、実務で利用される pgvector / Pinecone / Faiss / OpenSearch / Kendra / AI Search を比較します。

項目 pgvector Pinecone Faiss OpenSearch Kendra / AI Search
導入難易度 低(PostgreSQL拡張で即導入可) 低(APIベース) 中(ビルドやメモリ設定必要) 中(Elasticsearch互換) 低(マネージド)
コスト 低(自社運用のみ) 中〜高(従量課金) 低(ローカル利用前提) 高(マネージド課金+検索課金)
検索速度 中(CPU依存、インデックス調整で改善) 高(GPU/分散対応) 高(C++実装で超高速) 中(スケール構成で調整) 中(チューニング不可)

pgvectorは特に、「既存のPostgreSQL資産を活かしながらベクトル検索を追加したい」というニーズに最適です。
一方で、大量データを扱う本番RAGや分散検索を重視する場合は、PineconeやOpenSearchを検討するのも有効です。

「PostgreSQLを活かしたRAG構築」 のメリット整理

pgvectorを使う最大の利点は、「既存のPostgreSQLをそのままRAG基盤にできる」ことです。
新しいサービスやインフラを増やさず、既存DBの監視・バックアップ運用の仕組みを流用できます。

メリット 説明
導入が容易 既存PostgreSQLにCREATE EXTENSION vector;を実行するだけ
低コスト 外部サービス費用が不要で、RDSでも利用可能
SQLで扱える ベクトル検索も既存のSQL文に組み込みやすい
移行が容易 本番DBとの互換性を保ちながら徐々に拡張できる

このように、pgvectorは「RAGを社内環境で完結させたい企業」に最適な選択肢といえます。

まとめ

  • pgvectorは既存PostgreSQLの拡張として導入しやすく、移行リスクが低い

  • Dockerで検証 → 運用DBに導入 という2段階構成が最も安全

  • コストを抑えたRAG構築の実現手段として有力

Discussion