
生成AIとRAG(Retrieval-Augmented Generation)アプリケーションの初期段階では、エンジニアリングチームはPinecone、Weaviate、Qdrant、Milvusなどの特殊なスタンドアロン型ベクトルデータベースをこぞって採用しました。
しかし、既存のリレーショナルデータベースと並行して別のベクトルデータベースを運用すると、デュアルライト同期の失敗、結果整合性の遅延、アクセス制御ポリシーの重複、そして困難な分散トランザクションのロールバックといった深刻な運用上の問題が発生します。
pgvector (v0.7+) のリリースにより、PostgreSQLは本番環境のベクトル検索における主要なプラットフォームとしての地位を確立しました。高次元の埋め込みを標準のPostgreSQLテーブル内に直接保存することで、ACIDトランザクション、使い慣れたSQLセマンティクス、堅牢なバックアップツール、そして単一のアトミッククエリでリレーショナル外部キーに対してベクトルクエリを結合する機能が維持されます。
このガイドでは、本番環境でのインデックス戦略(HNSW vs IVFFlat)を分解し、メモリパラメータを最適化し、純粋なSQLでReciprocal Rank Fusion (RRF) を使用してハイブリッド検索を実装し、本番環境のPythonクライアントを構築します。
Estimate RAM usage, disk index size & maintenance_work_mem
Calculate exact RAM overhead, disk footprint, and indexing parameters (m, ef_construction) for PostgreSQL pgvector HNSW vector indexes. Compare halfvec and quantization savings.
運用データとベクトル埋め込みを分離した場合に何が起こるか考えてみましょう。
[The Dual-Database Trap]
User Action ──► Write to Primary Database (PostgreSQL)
│
▼ (CDC Pipeline / Debezium / Celery Worker)
Dual-Write Lag & Potential Desync!
▼
Write to Vector DB (Pinecone / Qdrant)
[The Unified pgvector Architecture]
User Action ──► Write to PostgreSQL (Atomic Transaction)
├── Relational Metadata (user_id, tenant_id, created_at)
└── High-Dimensional Vector (embedding vector(1536))
✓ Zero Synchronization Lag
✓ ACID Guarantees & Atomic Rollbacks
✓ Unified Row-Level Security (RLS)
pgvectorでは、ベクトル埋め込みは単なるネイティブデータ型です。トランザクションが失敗したりロールバックしたりしても、埋め込みはリレーショナルレコードと100%一貫性を保ちます。
拡張機能をインストールし、ベクトル次元サイズを定義します。次元サイズは埋め込みモデルと正確に一致する必要があります(例:OpenAI text-embedding-3-smallの場合は1,536、text-embedding-3-largeの場合は3,072)。
-- Enable the vector extension
CREATE EXTENSION IF NOT EXISTS vector;
-- Create production knowledge base table
CREATE TABLE document_chunks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
document_id UUID NOT NULL,
tenant_id UUID NOT NULL,
content TEXT NOT NULL,
metadata JSONB DEFAULT '{}'::jsonb,
embedding vector(1536) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
pgvectorは3つの距離演算子を提供します。
<=> コサイン距離: ベクトル間の角度を測定します(値は0から2の間で、0が同一)。正規化されたテキスト埋め込みの標準的なメトリックです。<-> ユークリッド距離 (L2): 直線的な空間距離を測定します。マグニチュードが重要な場合に最適です。<#> 負の内積: ドット積に-1を乗じたものと同等です。埋め込みモデルが事前に正規化されたベクトル(OpenAIやCohereなど)を生成する場合、内積はコサイン類似度と数学的に同一ですが、平方根の正規化ステップをスキップするため、20%から30%高速に計算されます!インデックスがない場合、PostgreSQLはすべてのベクトルに対して正確なシーケンシャルスキャン(O(n)のフラット検索)を実行します。100%正確ですが、テーブルが50,000ベクトルを超えると、フラットスキャンは本番環境では遅すぎます。
pgvectorは2つの近似最近傍(ANN)インデックスアルゴリズムを提供します。
O(\log n))で、再現率も優れています(98%以上)。-- Production HNSW Index Configuration
CREATE INDEX idx_document_chunks_hnsw_cosine
ON document_chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
m: ノードあたりの双方向リンクの最大数(デフォルト: 16)。高い値(例:24~32)は、メモリを犠牲にして高次元埋め込みの再現率を向上させます。ef_construction: インデックス構築中に評価される動的候補リストのサイズ(デフォルト: 64)。128に増やすと、グラフの接続性とクエリの精度が向上します。hnsw.ef_search: クエリ時の精度とレイテンシを制御するために実行時に設定します。-- Tune per-session or per-query search depth
SET hnsw.ef_search = 100; -- Default is 40; higher values yield higher recall
密なベクトル検索は、概念的な同義語(「自動車」が「車」に一致する)を理解するのに優れています。しかし、ベクトル検索は、部品番号、エラーコード(ERR_404_NULL)、固有名詞などの正確なキーワード検索には苦戦します。
業界のゴールドスタンダードは、フルテキスト検索(tsvector)とセマンティックベクトル距離を組み合わせたReciprocal Rank Fusion (RRF) によるハイブリッド検索です。
-- Hybrid Search using Reciprocal Rank Fusion in pure PostgreSQL
WITH semantic_search AS (
SELECT id, content, RANK() OVER (ORDER BY embedding <=> '[0.012, -0.045, ...]') AS rank
FROM document_chunks
WHERE tenant_id = 'a1b2c3d4-e5f6-7890-abcd-1234567890ab'
ORDER BY embedding <=> '[0.012, -0.045, ...]'
LIMIT 20
),
keyword_search AS (
SELECT id, content, RANK() OVER (ORDER BY ts_rank_cd(to_tsvector('english', content), query) DESC) AS rank
FROM document_chunks, plainto_tsquery('english', 'database connection pooling') query
WHERE tenant_id = 'a1b2c3d4-e5f6-7890-abcd-1234567890ab'
AND to_tsvector('english', content) @@ query
LIMIT 20
)
SELECT
COALESCE(s.id, k.id) AS id,
COALESCE(s.content, k.content) AS content,
COALESCE(1.0 / (60 + s.rank), 0.0) +
COALESCE(1.0 / (60 + k.rank), 0.0) AS rrf_score
FROM semantic_search s
FULL OUTER JOIN keyword_search k ON s.id = k.id
ORDER BY rrf_score DESC
LIMIT 10;
# db_vector_client.py
import os
from sqlalchemy import create_engine, select, text
from sqlalchemy.orm import declarative_base, Session
from pgvector.sqlalchemy import Vector
Base = declarative_base()
class DocumentChunk(Base):
__tablename__ = 'document_chunks'
id = Column(UUID, primary_key=True)
tenant_id = Column(UUID, nullable=False)
content = Column(Text, nullable=False)
embedding = Column(Vector(1536), nullable=False)
def query_similar_chunks(tenant_id: str, query_embedding: list[float], limit: int = 5):
engine = create_engine(os.getenv("DATABASE_URL"))
with Session(engine) as session:
# Cosine distance ordering using native pgvector operator
stmt = (
select(DocumentChunk)
.filter(DocumentChunk.tenant_id == tenant_id)
.order_by(DocumentChunk.embedding.cosine_distance(query_embedding))
.limit(limit)
)
return session.scalars(stmt).all()
RAGアプリケーションが現在スタンドアロンのvector databaseを使用しています。エンジニアリングチームは、新しいドキュメントがメインのPostgreSQLデータベースには表示されるものの、vector similarityによる検索ができないという問題に直面しています。この不一致の最も可能性の高い根本原因は何ですか?
1,536次元の1,000,000個のベクトルに対して、生のベクトルデータは約6GBのストレージを占有します。m=16のHNSWインデックスは約2.5GBのインデックスデータを追加します。最適な10ms未満のクエリレイテンシを実現するには、PostgreSQLサーバーが十分なshared_buffersとRAM(少なくとも16GBから32GB)を持ち、HNSWインデックス全体をメモリに保持できることを確認してください。
はい。1,000万から5,000万以上のベクトルでは、本番チームはPostgreSQLテーブルパーティショニング(例:tenant_idまたはcreated_at年によるパーティショニング)を使用します。個々のパーティションにローカルHNSWインデックスを作成することで、各インデックスをメモリバッファに収まる十分な小ささに保ちます。
HNSWインデックスがRAMに収まる場合、pgvectorは4msから12msのクエリレイテンシを提供し、専用のクラウドベクトルデータベースと同等かそれ以上の性能を発揮します。これにより、APIサーバーとサードパーティデータベースエンドポイント間のインターネットネットワーク転送遅延が解消されます。
AI CLIログの整形、Cron式の作成、JWTの解析、chmod権限の計算をオフラインで実行。

pgvectorとハイブリッド検索を組み合わせた堅牢なRAGアーキテクチャの構築方法を学び、全文ベクトル検索とBM25を組み合わせて検索精度を向上させ、HNSWインデックスを調整し、プロダクションPythonクライアントを出荷します。
続きを読む
pgvectorとsqlite-vecにおけるHNSWとIVFFlatベクトルインデックスアルゴリズムを比較。再現率、構築時間、メモリフットプリント、クエリレイテンシを分析します。
続きを読む
大規模なpgvectorとQdrantの比較について、メモリオーバーヘッド、HNSWリコール、テールレイテンシ(2026年)を網羅した包括的なガイドで、本番環境レベルのアーキテクチャとコード例を紹介します。
続きを読む