0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ベクトルDBを比較する:pgvector・Chroma・Qdrantの使い分け

0
Last updated at Posted at 2026-10-01

RAGやセマンティック検索を実装するとき、最初に迷いやすいのが「どのベクトルDBを使うか」です。既存のPostgreSQLに載せるべきか、Pythonで手軽に始められるChromaか、検索専用のQdrantか。

先に結論を書くと、業務データをSQLで管理しているなら pgvector、ローカルでRAGを素早く試すなら Chroma、ベクトル検索を独立サービスとして運用するなら Qdrant が選びやすいです。

この記事では、同じような3次元ベクトルを登録して検索しながら、それぞれの違いを確認します。

まず比較するポイント

ベクトルDBを選ぶとき、検索速度だけを見ると判断を誤りやすくなります。私は次の観点で比較しました。

観点 pgvector Chroma Qdrant
位置付け PostgreSQL拡張 AIアプリ向けDB ベクトル検索専用DB
始めやすさ PostgreSQLが必要 非常に簡単 Dockerで簡単
通常データとの結合 SQL JOINが得意 アプリ側で扱う Payloadで保持
フィルタ SQL Metadata filter Payload filter
向いている用途 既存業務DB、厳密な整合性 PoC、個人開発、小規模RAG 検索基盤、独立サービス

なお、どの製品を選んでも、検索品質を決める大きな要素はEmbeddingモデルとチャンク分割です。DBを変えただけで検索品質が大きく改善するわけではありません。

pgvector:既存のPostgreSQLを活かす

pgvectorはPostgreSQLの拡張機能です。ベクトルだけを別DBに切り出さず、ユーザー、権限、商品、文書などの既存テーブルと同じデータベースで管理できます。

公式ドキュメントでは、完全一致に近い検索に加えて、HNSWやIVFFlatによる近似最近傍検索もサポートされています。HNSWは検索性能と再現率のバランスがよい一方、インデックス作成時のメモリ消費が大きくなります。pgvector公式README

まずはPostgreSQLに拡張を有効化します。

CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id bigserial PRIMARY KEY,
  content text NOT NULL,
  category text NOT NULL,
  embedding vector(3) NOT NULL
);

3次元のサンプルデータを登録して、コサイン距離で検索します。

INSERT INTO documents (content, category, embedding)
VALUES
  ('PostgreSQLで全文検索を実装する', 'database', '[0.90, 0.10, 0.00]'),
  ('RAGのチャンク分割を考える', 'ai',       '[0.10, 0.90, 0.00]'),
  ('Dockerで開発環境を作る',       'infra',    '[0.05, 0.10, 0.85]');

SELECT id, content, category,
       embedding <=> '[0.12, 0.88, 0.00]'::vector AS distance
FROM documents
ORDER BY embedding <=> '[0.12, 0.88, 0.00]'::vector
LIMIT 2;

データ量が増えたら、検索用インデックスを追加します。

CREATE INDEX documents_embedding_hnsw_idx
ON documents
USING hnsw (embedding vector_cosine_ops);

実際に試してみて感じたpgvectorの強みは、検索結果に対してSQLの条件を自然に追加できることです。

SELECT id, content
FROM documents
WHERE category = 'ai'
ORDER BY embedding <=> '[0.12, 0.88, 0.00]'::vector
LIMIT 5;

すでにPostgreSQLを使っていて、検索対象の文書にも業務上の属性が多い場合は、まずpgvectorを検討するのが堅実です。

Chroma:RAGの試作を最短で始める

Chromaは、Embedding、文書、Metadataをコレクション単位で扱えるライブラリです。Pythonからの操作が簡単で、メモリ上だけで動かすことも、ローカルディスクに永続化することもできます。Chroma公式ドキュメント

インストールは次の1行です。

pip install chromadb

Embeddingをあらかじめ用意する場合は、次のように登録できます。

import chromadb

client = chromadb.PersistentClient(path="./.chroma")
collection = client.get_or_create_collection(name="documents")

collection.upsert(
    ids=["doc-1", "doc-2", "doc-3"],
    documents=[
        "PostgreSQLで全文検索を実装する",
        "RAGのチャンク分割を考える",
        "Dockerで開発環境を作る",
    ],
    metadatas=[
        {"category": "database"},
        {"category": "ai"},
        {"category": "infra"},
    ],
    embeddings=[
        [0.90, 0.10, 0.00],
        [0.10, 0.90, 0.00],
        [0.05, 0.10, 0.85],
    ],
)

result = collection.query(
    query_embeddings=[[0.12, 0.88, 0.00]],
    n_results=2,
    where={"category": "ai"},
)

print(result["documents"])

PersistentClientを使うと、プロセスを終了しても指定したディレクトリにデータが残ります。ノートブックでRAGを試したり、社内ツールのプロトタイプを作ったりする場合に便利でした。

一方で、業務データの更新、複雑なトランザクション、複数テーブルをまたぐ検索を中心に考えると、PostgreSQLほど自然には書けません。Chromaは「検索機能を持つアプリを素早く作る」ための選択肢として考えると理解しやすいです。

Qdrant:検索サービスを独立させる

Qdrantは、ベクトル検索を中心に設計されたサービスです。ベクトル、ID、JSON形式のPayloadを「Point」として保持し、コレクション単位で検索します。Qdrant公式ドキュメント

ローカルではDockerで起動できます。

docker run --rm \
  -p 6333:6333 \
  qdrant/qdrant

Pythonクライアントをインストールします。

pip install qdrant-client

登録と検索の最小例は次のとおりです。

from qdrant_client import QdrantClient, models

client = QdrantClient(url="http://localhost:6333")
collection_name = "documents"

if not client.collection_exists(collection_name):
    client.create_collection(
        collection_name=collection_name,
        vectors_config=models.VectorParams(
            size=3,
            distance=models.Distance.COSINE,
        ),
    )

client.upsert(
    collection_name=collection_name,
    points=[
        models.PointStruct(
            id=1,
            vector=[0.90, 0.10, 0.00],
            payload={"content": "PostgreSQLで全文検索を実装する", "category": "database"},
        ),
        models.PointStruct(
            id=2,
            vector=[0.10, 0.90, 0.00],
            payload={"content": "RAGのチャンク分割を考える", "category": "ai"},
        ),
        models.PointStruct(
            id=3,
            vector=[0.05, 0.10, 0.85],
            payload={"content": "Dockerで開発環境を作る", "category": "infra"},
        ),
    ],
)

hits = client.query_points(
    collection_name=collection_name,
    query=[0.12, 0.88, 0.00],
    query_filter=models.Filter(
        must=[
            models.FieldCondition(
                key="category",
                match=models.MatchValue(value="ai"),
            )
        ]
    ),
    with_payload=True,
    limit=2,
).points

for hit in hits:
    print(hit.score, hit.payload)

Qdrantの特徴は、Payloadによるフィルタをベクトル検索と組み合わせやすいことです。言語、テナント、公開状態、商品カテゴリなどをPayloadに持たせておけば、意味の近さと業務条件を同時に扱えます。

また、複数のベクトルを名前付きで持つ構成や、密ベクトルと疎ベクトルを組み合わせる構成にも向いています。検索部分をAPIサービスとして切り出したい場合は、pgvectorよりQdrantのほうが責務を分離しやすいと感じました。

どれを選ぶべきか

要件に応じた選択の流れを図にすると次の通りです。

私なら、次のように選びます。

  • 既存システムがPostgreSQL中心で、権限や在庫などの条件をSQLで厳密に扱うならpgvector
  • PythonでRAGの流れを確認したい、または小さなアプリを作りたいならChroma
  • ベクトル検索を独立したサービスとして運用し、Payload検索や将来の拡張も重視するならQdrant

ただし、最初から大量データを想定して複雑な構成にする必要はありません。私は最初にChromaやpgvectorで、次の項目を小さなデータセットで確認します。

  1. 期待する文書が上位に出るか
  2. MetadataやPayloadの条件を満たせるか
  3. 文書更新時に古いEmbeddingが残らないか
  4. バックアップと再インデックスの手順を説明できるか

近似検索を使う場合は、速度だけでなく再現率も確認します。pgvectorならインデックスなしの検索結果を基準にし、近似インデックス使用時の結果との差分を見ると、チューニングの方向性を判断しやすくなります。

まとめ

pgvector、Chroma、Qdrantは、単純な優劣ではなく得意な境界が異なります。

  • 業務データとの整合性とSQLを重視するならpgvector
  • 試作と実装速度を重視するならChroma
  • 専用の検索基盤と柔軟なPayload検索を重視するならQdrant

最終的な検索品質は、DB製品だけでは決まりません。Embeddingモデル、チャンクサイズ、Metadata設計、検索後の再ランキングまで含めて小さく検証し、運用要件に合うものを選ぶのが現実的です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?