---
title: "ベクトルDBとは？仕組み・インデックス構造・製品比較とpgvectorで動かす手順【2026年版】"
url: "https://www.issoh.co.jp/tech/details/7691/"
published: 2025-07-14
updated: 2026-10-10
categories: ["AI"]
publisher: "株式会社一創"
---

# ベクトルDBとは？仕組み・インデックス構造・製品比較とpgvectorで動かす手順【2026年版】

ベクトルDB（ベクトルデータベース）とは、テキストや画像を数百〜数千次元の数値配列に変換して保存し、「意味が近いもの」を距離の近さとして取り出すためのデータベースです。生成AIの社内検索やRAGの構成要素として名前を聞く機会が増えた一方、実装に入ると次元数の上限、インデックスのパラメータ、メタデータ絞り込みの挙動といった制約に必ずぶつかります。この記事では、ベクトル化からインデックス構造、製品選定までを公式ドキュメントの実値で整理し、Dockerとpgvectorを使って手元で登録から検索まで動かすコードも示します。

## まとめ：ベクトルDBとは何か、導入前に押さえる5つの要点

- **本質は「近似最近傍探索の永続化」**です。完全一致・範囲検索はリレーショナルデータベース、単語一致は全文検索エンジンが担当し、意味の近さだけをベクトル検索が引き受けます。
- **ベクトル化（エンベディング）は埋め込みモデルの選定でほぼ決まります。**OpenAIのtext-embedding-3-smallは1536次元、text-embedding-3-largeは3072次元で、`dimensions`パラメータによる縮小も可能です。
- **インデックスはHNSWとIVF系の2系統**です。pgvectorのHNSW既定値は`m=16`・`ef_construction=64`・`hnsw.ef_search=40`で、実装ごとに違います。
- **距離指標はコサイン距離・L2距離・内積**が主流ですが、正規化済みモデルなら順位は変わりません。
- **数十万件規模までならpgvector拡張で足ります。**専用データベースの追加は運用対象を1つ増やすため、メモリとフィルタ精度の2点が限界に達してから判断します。

まず試すなら、既存のPostgreSQLにpgvectorを入れる構成が最短です。Docker1コマンドとPython20行ほどで、文書の登録から意味の近い順の取り出しまで確認できます。

## ベクトルDBとは何か｜リレーショナルDB・全文検索との違いと役割分担

### ベクトルDBが引き受ける検索の種類と、結果が近似解になる理由

[AWSの用語解説「ベクトルデータベースとは」](https://aws.amazon.com/jp/what-is/vector-databases/)は、ベクトルデータベースをN次元空間の最も近い近傍を効率的かつ高速に検索するための機能を備えるものと説明し、その実現手段としてHNSW（Hierarchical Navigable Small World）や転置ファイルインデックス（IVF）を挙げています。

返ってくる結果が**近似解**である点は前提として押さえてください。全件との距離計算は件数に比例して遅くなるため、実用的な製品は精度をいくらか犠牲にして探索範囲を絞ります。後述するパラメータ調整は、この性質を制御する作業です。

### RDB・全文検索エンジン・ベクトル検索のクエリ別の守備範囲比較

ベクトル検索は既存の検索手段を置き換えるものではありません。3者の守備範囲は明確に分かれます。

| 検索の種類      | 適した仕組み            | 典型的なクエリ         |
| ---------- | ----------------- | --------------- |
| 完全一致・範囲・結合 | リレーショナルDB（B-tree） | 社員ID=1234、日付が今月 |
| 単語の一致・部分一致 | 全文検索（転置インデックス）    | 「有給休暇」を含む文書     |
| 意味・文脈の近さ   | ベクトル検索（ANN）       | 「休みを取りたい」に近い文書  |

「休みを取りたい」というクエリで「有給休暇の申請手順」を引き当てられるのがベクトル検索の価値です。逆に「社員ID=1234」のような一意な条件をベクトルで引くのは、精度・コストの両面で不利になります。絞り込みはRDBかフィルタ機能に任せ、意味の近さだけをベクトル検索に委ねてください。グラフ構造での関係探索まで含めた比較は[ベクトルデータベースとグラフデータベースの違い｜比較表・SQLとCypherの例・GraphRAGでの併用【2026年版】](/tech/details/4682/)で扱っています。

### ベクトルDBの1レコードに入るもの｜ベクトル・元テキスト・メタデータ

「ベクトルだけを保存するデータベース」と誤解されがちですが、実際の1レコードは3つの要素で構成されます。数値ベクトルだけでは人が読める結果を返せず、部署や日付で絞ることもできないためです。

```
{
  "id": 1024,
  "embedding": [0.0123, -0.0456, 0.0789, ...],
  "body": "有給休暇は申請システムから取得日の3営業日前までに申請します。",
  "metadata": { "dept": "人事", "updated_at": "2026-09-30", "source": "就業規則.pdf" }
}
```

`embedding`は検索に使う数値配列、`body`は検索結果として返す元テキスト、`metadata`は絞り込みや権限制御に使う属性です。製品ごとに呼び名は違い、Qdrantでは`payload`、Pineconeでは`metadata`と呼びます。設計で迷うのは、元テキストをベクトルDB側に持つか、RDBに正データを置いてIDだけ持つかの判断です。後者は整合性を保ちやすい代わりに、検索のたびにRDBへの問い合わせが1回増えます。

## ベクトル化（エンベディング）の仕組みと次元数がストレージを決める計算

### テキストや画像が埋め込みモデルで1本の数値ベクトルになるまで

ベクトル化とは、非構造化データを固定長の数値配列へ変換する処理です。テキストなら、埋め込みモデルが入力文をトークン列に分解し、学習済みのニューラルネットワークを通して1本の実数ベクトルを出力します。意味の近い文どうしが空間上で近くなるよう学習されているため、変換後の「文の意味」は、距離という単一の尺度で比較できる状態です。日本語に強いモデルの選び方は[埋め込みモデルとは？仕組みと日本語モデルの選び方・RAG実装での判断基準【2026年版】](/tech/details/16044/)で比較しています。

実装は「元データの分割（チャンク化）→埋め込みモデルによるベクトル生成→ベクトルと元テキスト・メタデータの保存」という流れです。ここで決まる次元数が、後段のストレージ量とインデックスの制約をそのまま規定します。Pythonでベクトルを生成するコードは[Pythonでembedding（ベクトル化）を生成する方法｜OpenAI APIとsentence-transformers](/tech/details/4081/)にまとめています。

### 次元数の制約と、100万件で約12.3GBになるストレージ見積もり

次元数はモデルによって固定されています。[OpenAIのEmbeddingsガイド](https://developers.openai.com/api/docs/guides/embeddings)によれば、既定の次元数はtext-embedding-3-smallが1536、text-embedding-3-largeが3072です。3系のモデルは`dimensions`APIパラメータで次元を削減でき、同ガイドは概念を表す性質を失わずに短縮できると説明しています。

次元数がストレージに与える影響は単純な計算で見積もれます。[pgvectorのREADME](https://github.com/pgvector/pgvector)によれば、`vector`型は1件あたり`4 * dimensions + 8`バイトを消費します。3072次元なら1件12,296バイトで、100万件のベクトル列だけで約12.3GBです（行のオーバーヘッドとインデックスは別途）。半精度の`halfvec`型（`2 * dimensions + 8`バイト）に切り替えれば約6.2GBに収まります。次元を落とすか精度を落とすかは、検索品質の実測と保存コストを突き合わせて決める判断になります。

## ベクトルインデックスの構造と、精度・速度・メモリのトレードオフ

### HNSWの多層グラフ構造と、m・ef\_constructionが精度に効く仕組み

ベクトルインデックス（vector index）の主流はHNSWです。Malkov と Yashunin が[arXiv:1603.09320](https://arxiv.org/abs/1603.09320)（2016年3月30日投稿、2018年8月14日改訂）で提案した近似最近傍探索のアルゴリズムで、ベクトルをノードとする多層グラフを構築し、上位層の粗いリンクで大まかな位置まで移動してから、下位層の密なリンクで近傍を精査します。

調整対象は2つです。`m`はノード1つが持つリンクの本数で、大きくすると精度が上がる代わりにインデックスが肥大します。`ef_construction`は構築時の候補リストの長さで、大きくすると再現率が上がる一方、構築時間の増加と挿入速度の低下を伴う設定です。検索時は別途`ef_search`（実装によっては`ef`）で精度と応答速度のバランスを取ります。値の決め方は[HNSWとは？階層グラフの仕組みとM・ef\_constructionの決め方を実装目線で解説【2026年版】](/tech/details/16468/)で掘り下げています。

### IVF系の転置ファイル構造と、量子化でメモリを削る代わりに失うもの

IVF（Inverted File）系は、事前にベクトル空間をクラスタに分割し、クエリに近いクラスタだけを走査する方式です。pgvectorのドキュメントはIVFFlatについて「HNSWより構築が速くメモリ消費が少ないが、クエリ性能は劣る」としており、HNSWのグラフがメモリに載らない規模で選択肢になります。反面、クラスタ分割には既存データの学習が必要で、「テーブルにデータが入った後にインデックスを作る」使い方が前提です。

IVFはしばしば量子化と組み合わせます。各次元を8bit整数に丸めるスカラー量子化や1bitに落とすバイナリ量子化は、メモリ使用量を下げる代わりに再現率も落ちる方式です。落ちた精度は、量子化インデックスで粗く絞ってから元のベクトルで再スコアリングする2段構えで取り戻します。HNSW・IVF・PQの使い分けは[近似最近傍探索とは？HNSW・IVF・PQの選び分けとRecall調整を実装目線で解説【2026年版】](/tech/details/16466/)で整理しました。

### pgvectorとQdrantで異なるHNSW既定パラメータの比較表

同じHNSWでも、実装ごとに既定値が異なります。ベンチマークを比較する際は、この既定値の差を揃えてから結果を読んでください。Qdrantの値は[リポジトリの既定設定ファイル](https://github.com/qdrant/qdrant/blob/master/config/config.yaml)で確認できます。

| 実装             | m（リンク数） | 構築時の候補リスト             | 検索時の候補リスト              |
| -------------- | ------- | --------------------- | ---------------------- |
| pgvector 0.8.7 | 16      | ef\_construction = 64 | hnsw.ef\_search = 40   |
| Qdrant 1.19.2  | 16      | ef\_construct = 100   | ef\_construct と同値（100） |

pgvectorとQdrantは`m`が同じ16である一方、構築時の候補リストはQdrantが100、pgvectorが64、検索時は100対40と差が開きます。既定のままで「Qdrantのほうが精度が高い」という結果が出たとしても、それはアルゴリズムの差ではなくパラメータの差である可能性が残ります。

## 類似度計算に使う距離指標の選び方｜コサイン・L2・内積の違い

### コサイン類似度と内積で検索順位が入れ替わる条件をPythonで確認

ベクトル間の近さは、コサイン距離・L2（ユークリッド）距離・内積のいずれかで測ります。コサイン類似度はベクトルの向きだけを見て長さを無視し、内積は長さの影響を受けます。この長さの扱いの違いは、検索順位に直接影響する要因です。次のコードは、向きがクエリとほぼ同じで長さが短い文書と、向きが少しずれるが長さが大きい文書を並べたものです。

```
import numpy as np

docs = ["有給休暇の申請手順", "有給休暇の付与日数と繰越", "経費精算の締め日"]
query = np.array([1.0, 0.9, 0.1, 0.0])
vecs = np.array([
    [0.5, 0.45, 0.05, 0.0],   # 向きはクエリとほぼ同じ・長さは短い
    [1.6, 1.2, 0.6, 0.3],     # 向きは少しずれる・長さが大きい
    [0.1, 0.0, 1.0, 0.9],     # 別トピック
])

def cosine(a, b):
    return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))

for i, d in enumerate(docs):
    print(f"{d}: cos={cosine(query, vecs[i]):.3f} dot={float(query @ vecs[i]):.3f}")
```

実行結果は次のとおりです。

```
有給休暇の申請手順: cos=1.000 dot=0.910
有給休暇の付与日数と繰越: cos=0.963 dot=2.740
経費精算の締め日: cos=0.110 dot=0.200
```

コサイン類似度では「申請手順」が1位（1.000）ですが、内積では「付与日数と繰越」が1位（2.740）に入れ替わります。長い文書ほどベクトルの長さが大きくなりやすいため、内積をそのまま使うと長文が上位に集まる偏りが生じます。

ただし、この入れ替わりが起きるのは正規化していないベクトルを使う場合に限られます。**指標はモデルが学習時に使ったものへ合わせるのが原則**ですが、OpenAIの埋め込みは長さ1に正規化済みで、[公式ガイドのFAQ](https://developers.openai.com/api/docs/guides/embeddings)も「コサイン類似度とユークリッド距離は同一の順位になる」「距離関数の選択は通常それほど問題にならない」と明記しています。正規化済みモデルを使う限り、指標選びで悩む必要はありません。

### pgvectorの距離演算子4種と、負の内積で符号を反転させる理由

pgvectorでは演算子で指標を指定します。`<->`がL2距離、`<=>`がコサイン距離、`<#>`が負の内積、`<+>`がL1距離です。`<#>`が符号を反転しているのは、PostgreSQLが昇順のインデックススキャンしかサポートしないためで、実際の内積を得るには結果に-1を掛けます。

## Dockerとpgvectorで最小構成のベクトルDBを作り検索まで試す手順

### Dockerでpgvector 0.8.7入りPostgreSQL 18の起動手順

ベクトルDBを手元で試すなら、pgvector入りのPostgreSQLイメージを起動するのが最短です。[Docker Hubの公式イメージ](https://hub.docker.com/r/pgvector/pgvector)は、READMEで`0.8.7-pg18-trixie`や`pg17`などのタグを案内しています。版を固定したいので、ここでは版番号付きのタグを使います。

```
docker run -d --name pgvector-demo \
  -e POSTGRES_PASSWORD=postgres \
  -p 5432:5432 \
  pgvector/pgvector:0.8.7-pg18-trixie

pip install "psycopg[binary]" pgvector openai numpy
```

pgvectorの0.8.7は2026年10月1日のリリースで、IVFFlatインデックス構築時のバッファオーバーフローが修正されています（[CHANGELOG](https://github.com/pgvector/pgvector/blob/master/CHANGELOG.md)）。0.8.6以前で運用している環境は、IVFFlatを使っているかどうかで更新の優先度が変わります。インストール手順をOS別に知りたい場合は[pgvectorとは？インストール手順（Windows・Ubuntu・Docker）と使い方【0.8.7対応】](/tech/details/6231/)を参照してください。

### テーブル定義とHNSWインデックスを作るSQLと演算子クラスの合わせ方

1536次元の埋め込みを格納し、コサイン距離でHNSWインデックスを張るまでは次のSQLで完了します。

```
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE documents (
  id      bigserial PRIMARY KEY,
  body    text NOT NULL,
  dept    text NOT NULL,
  embedding vector(1536)
);

CREATE INDEX ON documents
  USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);
```

演算子クラスは距離指標に対応し、コサイン距離なら`vector_cosine_ops`、L2距離なら`vector_l2_ops`、内積なら`vector_ip_ops`です。検索クエリの演算子とインデックスの演算子クラスが一致しないとインデックスが使われないため、必ず揃えます。

### Pythonから3件の文書を登録し意味の近い順に取り出すコード

上のテーブルに文書を入れて、クエリ文に近い順に返すところまでをPythonで通します。型の登録は[pgvector-python](https://github.com/pgvector/pgvector-python)の`register_vector`を使います。拡張を有効にした後でないと型を登録できないため、呼び出し順に注意してください。実行には環境変数`OPENAI_API_KEY`が必要です。

```
import numpy as np
import psycopg
from openai import OpenAI
from pgvector.psycopg import register_vector

client = OpenAI()  # OPENAI_API_KEY を環境変数から読む
DSN = "postgresql://postgres:postgres@localhost:5432/postgres"

def embed(texts):
    res = client.embeddings.create(model="text-embedding-3-small", input=texts)
    return [np.array(d.embedding) for d in res.data]

docs = [
    ("有給休暇は取得日の3営業日前までに申請します", "人事"),
    ("経費精算の締め日は毎月25日です", "経理"),
    ("営業日報は当日18時までに提出します", "営業"),
]

with psycopg.connect(DSN, autocommit=True) as conn:
    conn.execute("CREATE EXTENSION IF NOT EXISTS vector")
    register_vector(conn)  # 拡張を有効にした後に型を登録する
    for (body, dept), vec in zip(docs, embed([d[0] for d in docs])):
        conn.execute(
            "INSERT INTO documents (body, dept, embedding) VALUES (%s, %s, %s)",
            (body, dept, vec),
        )
    q = embed(["休みを取りたい"])[0]
    rows = conn.execute(
        "SELECT body, embedding <=> %s AS distance "
        "FROM documents ORDER BY embedding <=> %s LIMIT 3",
        (q, q),
    ).fetchall()
    for body, distance in rows:
        print(f"{distance:.3f}  {body}")
```

出力は距離の小さい順に並びます。クエリに「有給」という単語が入っていなくても、休暇の申請に関する文書が先頭に来るかどうかを確認してください。単語の一致に頼らず、意味の近い文書を検索できているかを判断するためです。`register_vector`が適用されるのはNumPy配列などで、Pythonのリストのまま渡すとPostgreSQLの配列型として送られてしまうため、埋め込みは`np.array`に変換してから渡しています。

### 検索クエリとhnsw.ef\_searchの調整｜LIMITより小さいと件数が揃わない

精度が足りない場合は`hnsw.ef_search`を既定の40から引き上げます。

```
BEGIN;
SET LOCAL hnsw.ef_search = 100;

SELECT id, body, embedding <=> $1 AS distance
FROM documents
ORDER BY embedding <=> $1
LIMIT 5;
COMMIT;
```

`SET LOCAL`はトランザクションブロック内でしか効かず、`BEGIN`なしで実行すると警告が出るだけで設定が反映されません。セッション全体に効かせたい場合は`SET`を使います。

ドキュメントは`ef_search`を上げると再現率が上がる代わりに速度が落ちると明記しています。既定の40は上位5件を返す用途には十分でも、上位50件を取ってリランクする構成では不足します。**取得件数（LIMIT）より`ef_search`が小さいと、そもそも件数が揃いません。**

## 主要ベクトルDB製品の比較｜2026年10月時点の現行版と選定軸

### 専用DB型｜Milvus・Qdrant・Weaviate・Pinecone・Chroma

分散構成・レプリケーション・メタデータフィルタリングを最初から備え、億単位のベクトルを想定した製品群です。Pineconeはフルマネージドのみの提供で、[公式の料金ページ](https://www.pinecone.io/pricing/)ではStarterプランが無料（ストレージ2GB・インデックス5個まで）、有料はBuilderが月額20ドル、Standardが最低月額50ドル、Enterpriseが最低月額500ドルです。製品の詳細は[Pineconeとは？サーバーレス型ベクトルDBの料金・制限値・実装と選び分け【2026年版】](/tech/details/15926/)で扱っています。

Milvusは3.0系で外部コレクションを導入し、2026年7月29日の3.0.0で稼働中のカラム追加・削除まで対応しました。[リリースページ](https://github.com/milvus-io/milvus/releases)を見ると、3.0系の更新と並行して2.6系の保守リリースも続いています（[Milvusとは？v3.0の外部コレクション・インデックス選定・デプロイ形態【2026年版】](/tech/details/15929/)）。QdrantはRust実装で単一バイナリ運用が容易、Weaviateはスキーマ定義とハイブリッド検索に強みがあり、選定基準は[Weaviateとは？ハイブリッド検索・マルチテナンシー・料金と選定基準【2026年版】](/tech/details/15927/)にまとめました。Chromaはプロトタイプ用途に向く軽量な選択肢で、詳細は[Chroma（ChromaDB）とは？ベクトルデータベースの仕組み・使い方・pgvector比較](/tech/details/4425/)で解説しています。

### 既存DB拡張・ライブラリ型｜pgvector・OpenSearch・FAISSの位置づけ

pgvectorはPostgreSQLの拡張として動くため、既存のトランザクション・バックアップ・権限管理をそのまま流用できます。同様に、Elasticsearch／OpenSearch、Redis、MongoDB Atlasなど既に運用中のミドルウェアがベクトル検索を内蔵している場合も、新規製品を足す前に検討すべき対象です。AWS上でコストを抑えたい場合は、オブジェクトストレージにベクトルを置く[Amazon S3 Vectors APIとは？操作一覧・料金・OpenSearch比較とRAG構築を解説【2026年GA版】](/tech/details/7773/)も候補に入ります。FAISSはデータベースではなくインデックスのライブラリで、永続化・分散・メタデータ管理は自前実装が前提です。検索アルゴリズムの検証や、バッチ処理でインデックスを作り直す用途に向きます。

| 製品       | 形態             | 自前運用の要否     | 現行版    | リリース日      |
| -------- | -------------- | ----------- | ------ | ---------- |
| Milvus   | 専用DB（OSS・分散）   | 必要（マネージドあり） | 3.0.2  | 2026-09-20 |
| Qdrant   | 専用DB（OSS・Rust） | 必要（マネージドあり） | 1.19.2 | 2026-10-05 |
| Weaviate | 専用DB（OSS）      | 必要（マネージドあり） | 1.40.0 | 2026-10-07 |
| Chroma   | 専用DB（OSS・軽量）   | 必要          | 1.5.9  | 2026-05-05 |
| Pinecone | マネージドのみ        | 不要          | 版の概念なし | 随時更新       |
| pgvector | PostgreSQL拡張   | 既存DBに同居     | 0.8.7  | 2026-10-01 |
| FAISS    | ライブラリ          | 永続化から自前     | 1.15.1 | 2026-09-16 |

この表の版は2026年10月10日時点で各プロジェクトのリリースページ（[Qdrant](https://github.com/qdrant/qdrant/releases)・[Weaviate](https://github.com/weaviate/weaviate/releases)・[Chroma](https://github.com/chroma-core/chroma/releases)・[FAISS](https://github.com/facebookresearch/faiss/releases)）から確認した値です。Weaviateは1.40系の公開後も1.39系・1.38系へ修正リリースを出しています。OSS製品はリリース間隔が短いため、採用検討時は最新版を改めて確認してください。月額費用の比較は[ベクトルデータベースの価格とおすすめ｜3タイプの料金体系比較とRAG用途の選び方【2026年版】](/column/details/16480/)で扱っています。

## 専用ベクトルDBの採否を分ける判断材料と、pgvectorで足りる条件

解説は導入のメリットに偏りがちですが、実際の設計では「入れない判断」のほうが難しくなります。専用製品を足すか、既存のPostgreSQLで済ませるか。判断が分かれるのは次の点です。

### 3,072次元の埋め込みをpgvectorに載せるとHNSWを張れない落とし穴

これは逆に、pgvectorを選んだときに踏む制約です。pgvectorの`vector`型は最大16,000次元を保持できますが、**HNSWインデックスを張れるのは`vector`型で2,000次元まで**です。つまりtext-embedding-3-large（3072次元）の出力をそのまま`vector(3072)`に入れると、格納はできてもHNSWインデックスを作成できません。

回避策としては、`halfvec`にキャストしてインデックスを張る（4,000次元まで対応）、バイナリ量子化を使う（64,000次元まで対応。ただし再現率が落ちるため元のベクトルによる再スコアリングとセットで使います）、埋め込み生成時に`dimensions`パラメータで1536次元以下へ縮小する、があります。`halfvec`を使う場合は、インデックス定義でキャストを明示します。次は`embedding`を`vector(3072)`で定義したテーブルの例です。

```
CREATE INDEX ON documents_large
  USING hnsw ((embedding::halfvec(3072)) halfvec_cosine_ops);
```

埋め込みモデルの選定は、格納先の制約とセットで決めてください。制約を知らずに大きなモデルを選ぶと、インデックス作成の段階で設計をやり直すことになります。

### メタデータ絞り込みで件数が落ちる「フィルタ後掛け」と製品別の対処

近似インデックスとメタデータフィルタの組み合わせは直感に反します。pgvectorのドキュメントは「フィルタはインデックスをスキャンした**後に**適用される」と明記したうえで、具体例として**条件が全行の10%に一致する場合、既定の`hnsw.ef_search=40`では平均4行しかマッチしない**と説明しています。「部署=営業」で上位10件を要求したのに数件しか返らない、という現象の原因は、このフィルタ適用の順序です。

最初に試すべき手当ては`iterative_scan`ではありません。pgvectorのドキュメントは、フィルタ列にインデックスを張るところから始めるのがよく、多くの場合これで高速かつ厳密な最近傍探索が得られるとして、B-treeインデックスの作成を第一の対処に挙げています。一致率が低い条件なら、これだけで解決します。

```
CREATE INDEX ON documents (dept);

SET hnsw.iterative_scan = strict_order;

SELECT id, body FROM documents
WHERE dept = '営業'
ORDER BY embedding <=> $1
LIMIT 10;
```

一致率が高くB-treeだけでは足りない場合、pgvector 0.8系の`hnsw.iterative_scan`を有効にすると、必要に応じてインデックスを追加スキャンして件数を確保します。順序の厳密さを緩めてよければ`relaxed_order`のほうが再現率は高く、厳密な距離順が必要ならマテリアライズドCTEで並べ直す方法がドキュメントに示されています。

この挙動は実装ごとに異なります。Qdrantはペイロードインデックスに基づく追加エッジをHNSWグラフに張り、探索中にフィルタを適用します。ただし[Qdrantのインデックス解説](https://qdrant.tech/documentation/manage-data/indexing/)は、ペイロードインデックスをコレクション作成直後、データ投入前に作るよう推奨しており、追加エッジはインデックス作成後にしか生成されません。Weaviateは[フィルタリングの解説](https://docs.weaviate.io/weaviate/concepts/filtering)のとおり、条件を満たすIDの許可リストを先に作るプレフィルタ方式で、v1.34以降はACORNと呼ぶフィルタ戦略が既定になっています。**メタデータでの絞り込みが検索要件の中心にあるなら、それは専用データベースを検討する妥当な理由になります。**逆に、絞り込みがほとんど発生しない全社ナレッジ検索のような用途では、この差は選定理由になりません。

### データ量が小さい段階で専用DBを足すと生まれる運用負債と移行の目安

専用データベースを追加すると、監視・バックアップ・バージョンアップ・障害対応の対象がもう1つ増え、さらにRDB側の正データとベクトル側の同期という整合性の問題を抱え込みます。データが少ないうちは、この運用コストが検索性能の利得を上回ります。

移行の判断材料は、件数の増加そのものよりも次の2点です。1つは**インデックスがメモリに載りきらなくなった時点**。pgvectorのドキュメントも「グラフが`maintenance_work_mem`に収まるとインデックス構築が大幅に速くなる」としており、収まらないと構築時に`hnsw graph no longer fits into maintenance_work_mem`という通知が出ます。もう1つは**メタデータフィルタ併用時の再現率が要件を満たせなくなった時点**です。この2つが観測されるまでは、既存のPostgreSQLで運用するほうが総コストは低く抑えられます。

### 採用と見送りを条件で決める判断表｜pgvectorか専用DBか

ここまでの判断材料を、条件ごとの結論にまとめます。

| 条件                   | 結論                     |
| -------------------- | ---------------------- |
| PostgreSQL運用中・数十万件まで | pgvectorで始める           |
| 3072次元モデルを使いたい       | halfvecか次元縮小で対応        |
| 属性絞り込みが検索の主条件        | 専用DBを検討する              |
| 索引がメモリに載らない          | 専用DBか分散構成へ移る           |
| 運用担当を増やせない           | マネージド型を選ぶ              |
| PoCで数日だけ試す           | ChromaかDockerのpgvector |

どの行にも当てはまらないなら、専用DBは入れません。検索品質の不満は、多くの場合データベースではなくチャンク分割と埋め込みモデルの見直しで改善します。

## RAG・類似検索・レコメンドでのベクトルDBの使われ方と組み合わせる技術

用途として最も多いのがRAG（Retrieval-Augmented Generation）です。社内文書をチャンクに分割してベクトル化し、質問に近い数件を大規模言語モデルのプロンプトへ差し込むことで、モデルが学習していない自社固有の情報に基づく回答を生成させます。実装手順は[LangChainでRAGを構築する手順｜v1.3系のコード例とlangchain-classic移行](/tech/details/2332/)で扱っています。

ベクトル検索だけでは、製品型番や社内略語のような「単語そのもの」で引くべき質問を取りこぼします。実務のRAGでは、BM25とベクトル検索を並べて順位を統合する[ハイブリッド検索とは？RAGでBM25とベクトル検索を統合する仕組み・RRF・実装コード](/tech/details/8014/)や、上位候補を並べ直す[リランクモデルとは？ベクトル検索と組み合わせる種類・仕組み・選び方【2026年版】](/tech/details/4413/)を組み合わせるのが一般的です。社内文書の検索基盤をRAGとして組む場合は、データ整備から権限制御まで含めて[RAG構築支援](https://www.issoh.co.jp/service/ai/rag/)で相談を受けています。

ほかに類似画像検索、閲覧履歴からのレコメンド、表記ゆれを吸収したFAQマッチングが定番です。いずれも「キーワードは一致しないが意味は近い」データを引き当てる点で共通します。裏返せば、キーワード一致で足りる用途にベクトル検索を持ち込む必然性はありません。

## よくある質問

ベクトルDBについて、検索でよく調べられている質問に短く答えます。

### ベクトルDBとは何ですか？

ベクトルデータベースの略称で、テキストや画像を数値ベクトルに変換した状態で保存し、クエリベクトルに距離が近いものを返すデータベースを指します。内部では近似最近傍探索（ANN）のインデックスを使うため、結果は厳密な最近傍とは限らず、精度と速度のバランスをパラメータで調整する仕組みです。この「近似でよい」という割り切りが、全件走査との速度差を生んでいます。

### ベクトル化とは何を指しますか？

データを数値ベクトルへ変換する処理全般を指し、TF-IDFのような統計的手法も含みます。ただしベクトルデータベースの文脈で扱うのは、学習済みモデルによって意味の近さが距離に反映される「エンベディング」のほうです。OpenAIのtext-embedding-3-smallなら既定で1536個の実数からなるベクトルが出力されます。

### ベクトルインデックスとは何ですか？

高次元ベクトルの近傍探索を高速化するためのデータ構造です。多層グラフを構築するHNSWと、空間をクラスタ分割して候補を絞るIVF系が主流です。全件との距離計算を避けて一部だけを走査するため、精度と速度がパラメータで交換関係にあります。pgvectorのHNSWでは`m`・`ef_construction`・`hnsw.ef_search`がその調整点です。

### 無料で使えるベクトルデータベースはありますか？

あります。Milvus・Qdrant・Weaviate・Chroma・FAISSはいずれもオープンソースで、自前のサーバーやコンテナ上で無償利用できます。PostgreSQLを運用しているならpgvector拡張の追加が最も手間の少ない選択肢で、本文のDockerコマンドを使えば数分での起動が可能です。マネージドではPineconeのStarterプランが無料で、ストレージ2GB・インデックス5個まで追加費用なく使えます（2026年10月時点）。

### ベクトル検索とセマンティック検索はどう違いますか？

セマンティック検索は「意味を汲んで検索する」という目的を指す言葉で、ベクトル検索はそれを実現する手段の1つです。両者は対立する概念ではなく包含関係にあり、セマンティック検索はクエリ拡張やナレッジグラフなど、ベクトル検索以外の手段でも実装されます。詳細は[ベクトル検索とセマンティック検索の違い：包含関係・仕組み・pgvectorでの実装と使い分け](/tech/details/9159/)で整理しています。

## 関連記事

- [ベクトルデータベースとグラフデータベースの違い｜比較表・SQLとCypherの例・GraphRAGでの併用【2026年版】](/tech/details/4682/)：関係探索が必要なときの比較
- [ベクトル検索とセマンティック検索の違い：包含関係・仕組み・pgvectorでの実装と使い分け](/tech/details/9159/)：用語の整理
- [pgvectorとは？インストール手順（Windows・Ubuntu・Docker）と使い方【0.8.7対応】](/tech/details/6231/)：本記事の手順の詳細版
- [近似最近傍探索とは？HNSW・IVF・PQの選び分けとRecall調整を実装目線で解説【2026年版】](/tech/details/16466/)：索引構造の深掘り
- [LangChainでRAGを構築する手順｜v1.3系のコード例とlangchain-classic移行](/tech/details/2332/)：RAGへの組み込み

---

出典: [ベクトルDBとは？仕組み・インデックス構造・製品比較とpgvectorで動かす手順【2026年版】](<https://www.issoh.co.jp/tech/details/7691/>)（株式会社一創）
