- 1. なぜVector Databaseなのか
- 2. ベクトルエンベディングの基礎(きそ)
- 3. 距離(きょり)メトリクス(類似度測定)
- 4. インデキシングアルゴリズム
- 5. Vector Database比較
- 6. pgvector ディープダイブ
- 7. ハイブリッド検索
- 8. メタデータフィルタリング
- 9. プロダクション運用
- 10. 性能ベンチマーク
- 11. コスト分析
- 12. クイズ
- 13. 参考資料(さんこうしりょう)
1. なぜVector Databaseなのか
1.1 従来(じゅうらい)の検索の限界
従来のデータベースは正確なキーワードマッチングに基づいています。「子犬(こいぬ)が公園(こうえん)で遊(あそ)んでいる」で検索すると、「犬(いぬ)が芝生(しばふ)で走(はし)っている」は見つかりません。2つの文は意味的にほぼ同じですが、キーワードが異なるためです。
従来の検索: "子犬 公園" → キーワードマッチ → "子犬"と"公園"を含む文書のみ返却
ベクトル検索: "子犬 公園" → 意味ベクトル化 → 類似した意味の全文書を返却
→ "犬が芝生で走っている" ✅ 発見
→ "ペットの散歩スポット推薦" ✅ 発見
1.2 Vector Databaseが解決する問題
Vector Databaseはデータを高次元(こうじげん)ベクトル(数値配列)として保存し、ベクトル間の類似度(るいじど)に基づいて検索します。
主要ユースケース:
| 領域 | 説明 | 例 |
|---|---|---|
| RAG(検索拡張生成) | LLMに関連文書コンテキストを提供 | ChatGPT + 社内文書 |
| セマンティック検索 | 意味ベースの検索 | 自然言語質問検索 |
| レコメンドシステム | 類似アイテムの発見 | 商品/コンテンツ推薦 |
| 画像検索 | 視覚的類似性 | 「この服に似た商品」 |
| 異常検知 | 正常パターンから逸脱したデータ | 不正取引検知 |
| 重複検出 | 類似コンテンツの識別 | 盗作検知、重複文書 |
1.3 市場成長
Vector Database市場は2024年の15億ドルから2028年に約60億ドルへの成長が見込まれています。RAGパイプラインの爆発的な採用が主要な推進力です。
2. ベクトルエンベディングの基礎(きそ)
2.1 エンベディングとは
エンベディングとは、テキスト、画像(がぞう)、音声(おんせい)などの非構造化データを高次元空間の数値ベクトルに変換(へんかん)することです。意味的に類似したデータはベクトル空間で近くに位置します。
from openai import OpenAI
client = OpenAI()
# テキストをベクトルに変換
response = client.embeddings.create(
model="text-embedding-3-large",
input="Vector DatabaseはAI時代の重要なインフラです"
)
embedding = response.data[0].embedding
print(f"次元数: {len(embedding)}") # 3072
print(f"ベクトルサンプル: {embedding[:5]}") # [0.023, -0.041, 0.017, ...]
2.2 テキストエンベディングモデル比較
| モデル | プロバイダー | 次元 | MTEBスコア | 費用 | 特徴 |
|---|---|---|---|---|---|
| text-embedding-3-large | OpenAI | 3072 | 64.6 | 有料 | 次元削減サポート |
| text-embedding-3-small | OpenAI | 1536 | 62.3 | 低コスト | コスパ優秀 |
| embed-v3.0 | Cohere | 1024 | 64.5 | 有料 | 多言語優秀 |
| BGE-M3 | BAAI | 1024 | 68.2 | 無料 | OSS最強 |
| Jina-embeddings-v3 | Jina AI | 1024 | 65.5 | 無料 | 多言語特化 |
| all-MiniLM-L6-v2 | SBERT | 384 | 56.3 | 無料 | 軽量高速 |
| nomic-embed-text | Nomic | 768 | 62.4 | 無料 | ロングコンテキスト |
2.3 画像エンベディング
CLIP(Contrastive Language-Image Pre-Training)モデルは、テキストと画像を同じベクトル空間にマッピングします。
from sentence_transformers import SentenceTransformer
from PIL import Image
model = SentenceTransformer("clip-ViT-B-32")
# 画像エンベディング
img = Image.open("cat_photo.jpg")
img_embedding = model.encode(img)
# テキストエンベディング(同じベクトル空間)
text_embedding = model.encode("a cute orange cat")
# テキストで画像検索が可能!
from numpy import dot
from numpy.linalg import norm
similarity = dot(img_embedding, text_embedding) / (
norm(img_embedding) * norm(text_embedding)
)
print(f"類似度: {similarity:.4f}") # 0.28+ (関連があれば高い)
2.4 マルチモーダルエンベディング
最新モデルはテキスト、画像、音声を1つのベクトル空間に統合します。
テキスト: "海の上の夕焼け" ──┐
├──→ 同一ベクトル空間 → 類似度比較可能
画像: (夕焼けの写真) ──┘
3. 距離(きょり)メトリクス(類似度測定)
3.1 コサイン類似度(Cosine Similarity)
2つのベクトル間の角度(かくど)を測定します。ベクトルの大きさ(長さ)は無視し、方向のみを比較します。
import numpy as np
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 例: 3次元ベクトル
vec_a = np.array([1, 2, 3])
vec_b = np.array([2, 4, 6]) # 同じ方向、大きさのみ異なる
vec_c = np.array([-1, -2, -3]) # 反対方向
print(cosine_similarity(vec_a, vec_b)) # 1.0 (完全に同じ方向)
print(cosine_similarity(vec_a, vec_c)) # -1.0 (完全に反対方向)
使用場面: テキストエンベディング(最も一般的)、正規化されたベクトル
3.2 ユークリッド距離(Euclidean Distance / L2)
2つのベクトル間の直線距離を測定します。値が小さいほど類似しています。
def euclidean_distance(a, b):
return np.linalg.norm(a - b)
vec_a = np.array([1, 2])
vec_b = np.array([4, 6])
print(euclidean_distance(vec_a, vec_b)) # 5.0
使用場面: ベクトルの大きさが意味を持つ場合、クラスタリング
3.3 内積(ないせき)(Dot Product / Inner Product)
2つのベクトルの内積です。方向と大きさの両方を考慮します。
def dot_product(a, b):
return np.dot(a, b)
vec_a = np.array([1, 2, 3])
vec_b = np.array([4, 5, 6])
print(dot_product(vec_a, vec_b)) # 32
使用場面: Maximum Inner Product Search(MIPS)、正規化されたベクトルではコサイン類似度と同等
3.4 マンハッタン距離(Manhattan Distance / L1)
各次元の絶対差の合計です。
def manhattan_distance(a, b):
return np.sum(np.abs(a - b))
vec_a = np.array([1, 2, 3])
vec_b = np.array([4, 6, 3])
print(manhattan_distance(vec_a, vec_b)) # 7 (3 + 4 + 0)
3.5 メトリクス選択ガイド
テキストエンベディング検索 → コサイン類似度(デフォルト推奨)
画像類似度検索 → ユークリッド距離
レコメンドシステム(MIPS) → 内積
高次元スパースベクトル → コサイン類似度
クラスタリング / 分類 → ユークリッド距離
4. インデキシングアルゴリズム
ベクトルが数百万個ある場合、全ベクトルと1つずつ比較(Brute-force)すると遅すぎます。インデキシングアルゴリズムは検索速度を数千倍高速化します。
4.1 HNSW(Hierarchical Navigable Small World)
最も広く使われているANN(Approximate Nearest Neighbor)アルゴリズムです。
動作原理(どうさげんり):
Layer 3: [A] ────────────────── [B] (少数ノード、長距離リンク)
\ /
Layer 2: [A] ── [C] ── [D] ── [B] (中間ノード)
\ / \ / \ / \
Layer 1: [A]-[E]-[C]-[F]-[D]-[G]-[B] (大部分のノード、短距離リンク)
| | | | | | |
Layer 0: [全ベクトルが存在する基本層] (全ノード)
- 上位レイヤーで大まかな位置を特定し、下位レイヤーで精密検索
- グラフベースのためメモリ使用量が多いが、非常に高速
# QdrantでのHNSW設定例
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, HnswConfigDiff
client = QdrantClient("localhost", port=6333)
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(
size=1536,
distance="Cosine"
),
hnsw_config=HnswConfigDiff(
m=16, # ノード当たり接続数(高いほど正確、メモリ増加)
ef_construct=128, # インデックス構築時の探索範囲
full_scan_threshold=10000 # この数以下はbrute-force
)
)
主要パラメータ:
| パラメータ | 説明 | デフォルト | 効果 |
|---|---|---|---|
| M | ノード当たり接続数 | 16 | 高くすると精度/メモリ増加 |
| ef_construct | 構築探索範囲 | 128 | 高くするとインデックス品質向上 |
| ef_search | 検索探索範囲 | 64 | 高くすると検索精度向上、速度低下 |
4.2 IVF(Inverted File Index)
ベクトルをクラスタに分割し、検索時に最も近いクラスタのみを探索します。
ベクトル空間:
┌─────────────────────────────────┐
│ * * X * │
│ * Cluster1 * * │
│ * * X │
│ * * Cluster2 * │
│ * * * * │
│ * * │
│ * * * X │
│ Cluster3 Cluster4 │
│ * * * * * * │
└─────────────────────────────────┘
X = クラスタ中心(centroid)
検索: クエリに最も近いクラスタ(nprobe個)内のみ検索
4.3 IVF-PQ(IVF + Product Quantization)
PQはベクトルを圧縮してメモリ使用量を削減します。
# FAISSでIVF-PQインデックス作成
import faiss
dimension = 1536
nlist = 256 # クラスタ数
m_pq = 48 # サブベクトル数(次元をm_pq個に分割)
nbits = 8 # 各サブベクトルのコードブックサイズ
quantizer = faiss.IndexFlatL2(dimension)
index = faiss.IndexIVFPQ(quantizer, dimension, nlist, m_pq, nbits)
# 学習データでクラスタ + コードブック学習
index.train(training_vectors)
index.add(all_vectors)
# 検索時のnprobe設定
index.nprobe = 16 # 探索するクラスタ数
distances, indices = index.search(query_vector, k=10)
メモリ比較:
元データ(float32, 1536次元): 1536 x 4 bytes = 6,144 bytes/ベクトル
PQ圧縮(48サブベクトル): 48 x 1 byte = 48 bytes/ベクトル
→ 128倍圧縮!1億ベクトル: 614GB → 4.8GB
4.4 ScaNN(Scalable Nearest Neighbors)
Googleが開発(かいはつ)したアルゴリズムです。非対称ハッシュと量子化を組み合わせ、高いrecallでも高速な検索を提供します。
4.5 Annoy(Approximate Nearest Neighbors Oh Yeah)
Spotifyが開発したアルゴリズムです。空間をランダムなハイパープレーンで再帰的に分割し、ツリーを構築します。読み取り専用インデックスでメモリマップ方式をサポートし、複数プロセスで共有可能です。
4.6 アルゴリズム比較
| アルゴリズム | 検索速度 | メモリ | インデックス構築 | 精度 | 適合規模 |
|---|---|---|---|---|---|
| Flat(Brute-force) | 遅い | 高い | なし | 100% | 10万以下 |
| HNSW | 非常に速い | 高い | 遅い | 非常に高い | 数百万 |
| IVF-Flat | 速い | 中間 | 普通 | 高い | 数千万 |
| IVF-PQ | 速い | 低い | 普通 | 中間 | 数億 |
| ScaNN | 非常に速い | 中間 | 普通 | 高い | 数億 |
| Annoy | 速い | 低い | 速い | 中間 | 数千万 |
5. Vector Database比較
5.1 主要ソリューション比較表
| 特性 | Pinecone | Weaviate | Qdrant | Milvus | Chroma | pgvector |
|---|---|---|---|---|---|---|
| タイプ | マネージドSaaS | OSS/クラウド | OSS/クラウド | OSS | OSS | PostgreSQL拡張 |
| インデックス | 独自アルゴリズム | HNSW | HNSW | HNSW/IVF/DiskANN | HNSW | HNSW/IVF |
| ハイブリッド検索 | Sparse-Dense | BM25 + Vector | Sparse + Dense | サポート | 制限的 | Full-text + Vector |
| フィルタリング | メタデータフィルタ | GraphQLフィルタ | Payloadフィルタ | 属性フィルタ | Where句 | SQL WHERE |
| マルチテナンシー | ネームスペース | テナント分離 | コレクション/Payload | パーティション | コレクション | スキーマ/RLS |
| 最大次元 | 20,000 | 65,535 | 65,535 | 32,768 | 制限なし | 2,000 |
| 分散処理 | 自動 | Raft合意 | Raft合意 | 分散アーキテクチャ | 非サポート | Citus拡張 |
| SDK | Python/JS/Go/Java | Python/JS/Go/Java | Python/JS/Rust/Go | Python/JS/Go/Java | Python/JS | SQL |
| 価格 | Pod/Serverlessプラン | OSS無料 | OSS無料 | OSS無料 | OSS無料 | 無料 |
5.2 Pinecone
完全マネージドVector Databaseです。インフラ管理なしでAPIのみで使用します。
from pinecone import Pinecone, ServerlessSpec
pc = Pinecone(api_key="YOUR_KEY")
# インデックス作成
pc.create_index(
name="my-index",
dimension=1536,
metric="cosine",
spec=ServerlessSpec(
cloud="aws",
region="us-east-1"
)
)
index = pc.Index("my-index")
# ベクトルアップサート
index.upsert(
vectors=[
("id1", [0.1, 0.2, ...], {"title": "文書タイトル", "category": "tech"}),
("id2", [0.3, 0.4, ...], {"title": "別の文書", "category": "science"}),
],
namespace="articles"
)
# 検索(フィルタ + ベクトル)
results = index.query(
vector=[0.15, 0.25, ...],
top_k=5,
filter={"category": "tech"},
namespace="articles",
include_metadata=True
)
利点: 完全マネージド、即座スケーリング、Serverlessオプション 欠点: ベンダーロックイン、コスト高い、セルフホスティング不可
5.3 Weaviate
GraphQLベースのAPIと内蔵ベクトル化モジュールを提供するオープンソースVector Databaseです。
import weaviate
from weaviate.classes.config import Configure, Property, DataType
client = weaviate.connect_to_local()
# コレクション作成(内蔵ベクトル化)
collection = client.collections.create(
name="Article",
vectorizer_config=Configure.Vectorizer.text2vec_openai(
model="text-embedding-3-small"
),
properties=[
Property(name="title", data_type=DataType.TEXT),
Property(name="content", data_type=DataType.TEXT),
Property(name="category", data_type=DataType.TEXT),
]
)
# データ追加(自動ベクトル化)
articles = client.collections.get("Article")
articles.data.insert(
properties={
"title": "Vector DBガイド",
"content": "ベクトルデータベースはAI時代の核心...",
"category": "tech"
}
)
# セマンティック検索
response = articles.query.near_text(
query="人工知能インフラ",
limit=5,
filters=weaviate.classes.query.Filter.by_property("category").equal("tech")
)
利点: 内蔵ベクトル化、GraphQL API、モジュールエコシステム 欠点: リソース消費が多い、学習曲線
5.4 Qdrant
Rustで書かれた高性能Vector Databaseです。ペイロードフィルタリングと量子化に強みがあります。
from qdrant_client import QdrantClient
from qdrant_client.models import (
Distance, VectorParams, PointStruct,
Filter, FieldCondition, MatchValue
)
client = QdrantClient("localhost", port=6333)
# コレクション作成
client.create_collection(
collection_name="articles",
vectors_config=VectorParams(
size=1536,
distance=Distance.COSINE
)
)
# ベクトルアップサート
client.upsert(
collection_name="articles",
points=[
PointStruct(
id=1,
vector=[0.1, 0.2, ...],
payload={"title": "Vector DBガイド", "category": "tech", "views": 1500}
),
]
)
# フィルタ + ベクトル検索
results = client.search(
collection_name="articles",
query_vector=[0.15, 0.25, ...],
query_filter=Filter(
must=[
FieldCondition(key="category", match=MatchValue(value="tech")),
]
),
limit=5
)
利点: Rustベースの性能、きめ細かいフィルタリング、Scalar/Binary量子化 欠点: エコシステムが比較的小さい
5.5 ChromaDB
軽量で開発者(かいはつしゃ)フレンドリーなオープンソースVector Databaseです。プロトタイピングに最適です。
import chromadb
client = chromadb.PersistentClient(path="./chroma_db")
collection = client.create_collection(
name="articles",
metadata={"hnsw:space": "cosine"}
)
# ドキュメント追加(自動エンベディング)
collection.add(
documents=["Vector DBはAIインフラの核心です", "RAGは検索拡張生成です"],
metadatas=[{"category": "tech"}, {"category": "ai"}],
ids=["doc1", "doc2"]
)
# 検索
results = collection.query(
query_texts=["人工知能データベース"],
n_results=5,
where={"category": "tech"}
)
利点: 超簡単API、内蔵エンベディング、ローカル実行 欠点: プロダクションスケーリングの制限、分散非サポート
6. pgvector ディープダイブ
6.1 なぜpgvectorなのか
すでにPostgreSQLを使用しているなら、別のVector Databaseなしで既存インフラにベクトル検索を追加できます。SQLの豊富な機能とベクトル検索を組み合わせます。
6.2 インストールとセットアップ
-- PostgreSQL 14+が必要
-- 拡張インストール
CREATE EXTENSION IF NOT EXISTS vector;
-- ベクトルカラムを持つテーブル作成
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT,
category TEXT,
embedding VECTOR(1536), -- OpenAI text-embedding-3-small次元
created_at TIMESTAMPTZ DEFAULT NOW()
);
6.3 データ挿入と検索
-- ベクトル挿入
INSERT INTO documents (title, content, category, embedding)
VALUES (
'Vector DBガイド',
'Vector DatabaseはAI時代の核心...',
'tech',
'[0.1, 0.2, 0.3, ...]'::vector -- 1536次元ベクトル
);
-- コサイン距離検索(最も類似した5件)
SELECT id, title, 1 - (embedding <=> '[0.15, 0.25, ...]'::vector) AS similarity
FROM documents
WHERE category = 'tech'
ORDER BY embedding <=> '[0.15, 0.25, ...]'::vector
LIMIT 5;
-- L2距離検索
SELECT id, title, embedding <-> '[0.15, 0.25, ...]'::vector AS distance
FROM documents
ORDER BY embedding <-> '[0.15, 0.25, ...]'::vector
LIMIT 5;
6.4 HNSW vs IVFFlatインデックス
-- HNSWインデックス(推奨)
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 128);
-- 検索時のef_search設定
SET hnsw.ef_search = 100;
-- IVFFlatインデックス
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100); -- クラスタ数(sqrt(rows)推奨)
-- 検索時のprobes設定
SET ivfflat.probes = 10;
HNSW vs IVFFlat比較:
| 特性 | HNSW | IVFFlat |
|---|---|---|
| 検索速度 | より速い | 速い |
| インデックス構築 | 遅い | 速い |
| メモリ | より多い | より少ない |
| 精度(Recall) | より高い | 中間 |
| リアルタイム挿入 | 優秀 | 再構築が必要な場合あり |
| 推奨 | デフォルト選択 | メモリ制約がある場合 |
6.5 クエリ最適化
-- 1. 部分インデックス(特定カテゴリのみ)
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WHERE category = 'tech';
-- 2. フィルタ + ベクトル検索のパーティション活用
-- 遅いパターン: ベクトル検索後にフィルタ
SELECT * FROM documents
WHERE category = 'tech'
ORDER BY embedding <=> query_vec
LIMIT 10;
-- 速いパターン: パーティションテーブル活用
CREATE TABLE documents_tech PARTITION OF documents
FOR VALUES IN ('tech');
-- 3. EXPLAINでインデックス使用確認
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, title
FROM documents
ORDER BY embedding <=> '[0.15, 0.25, ...]'::vector
LIMIT 5;
7. ハイブリッド検索
7.1 なぜハイブリッド検索なのか
ベクトル検索だけでは不十分な場合があります。
クエリ: "PostgreSQL 16 リリースノート"
ベクトル検索のみ: "MySQL 8.0 新機能"も高い類似度(似た意味)
キーワード検索のみ: "PostgreSQL 16"が正確に含まれる文書のみ
ハイブリッド検索: 意味的に類似 + "PostgreSQL 16"を含む = 最適な結果
7.2 BM25 + Vector結合
# Weaviateのハイブリッド検索
response = articles.query.hybrid(
query="PostgreSQL vector search performance",
alpha=0.5, # 0 = キーワードのみ, 1 = ベクトルのみ, 0.5 = バランス
limit=10,
fusion_type="relative_score"
)
7.3 Reciprocal Rank Fusion(RRF)
2つの検索結果のランキングを統合するアルゴリズムです。
def reciprocal_rank_fusion(keyword_results, vector_results, k=60):
"""
RRFスコア = sum(1 / (k + rank_i))
k = 60が一般的
"""
scores = {}
for rank, doc_id in enumerate(keyword_results):
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
for rank, doc_id in enumerate(vector_results):
scores[doc_id] = scores.get(doc_id, 0) + 1 / (k + rank + 1)
return sorted(scores.items(), key=lambda x: x[1], reverse=True)
# 例
keyword_hits = ["doc_A", "doc_B", "doc_C", "doc_D"]
vector_hits = ["doc_C", "doc_A", "doc_E", "doc_B"]
fused = reciprocal_rank_fusion(keyword_hits, vector_hits)
# doc_Aとdoc_Cが両方で上位 → 最終上位
8. メタデータフィルタリング
8.1 フィルタリング戦略
ベクトル検索とメタデータフィルタを組み合わせる3つの戦略があります。
Pre-filtering: フィルタ適用 → フィルタされたベクトルのみ検索(正確だが遅い場合あり)
Post-filtering: ベクトル検索 → 結果にフィルタ適用(速いが結果が少ない場合あり)
In-filtering: 検索中にフィルタを同時適用(最適だが実装が複雑)
8.2 Qdrant高度フィルタリング
from qdrant_client.models import Filter, FieldCondition, MatchValue, Range
results = client.search(
collection_name="products",
query_vector=query_embedding,
query_filter=Filter(
must=[
FieldCondition(key="category", match=MatchValue(value="electronics")),
FieldCondition(key="price", range=Range(gte=100, lte=500)),
],
must_not=[
FieldCondition(key="out_of_stock", match=MatchValue(value=True)),
],
should=[
FieldCondition(key="brand", match=MatchValue(value="Apple")),
FieldCondition(key="brand", match=MatchValue(value="Samsung")),
]
),
limit=10
)
9. プロダクション運用
9.1 シャーディング戦略
水平シャーディング: データを複数ノードに分散
┌─ Node 1 ─┐ ┌─ Node 2 ─┐ ┌─ Node 3 ─┐
│ Shard 1 │ │ Shard 2 │ │ Shard 3 │
│ 33%データ │ │ 33%データ │ │ 33%データ │
└───────────┘ └───────────┘ └───────────┘
↕ 検索時にすべてのノードにクエリ後マージ
9.2 レプリケーション
# Qdrantレプリケーション設定
client.create_collection(
collection_name="articles",
vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
replication_factor=3, # 3ノードにレプリケート
write_consistency_factor=2 # 2ノード確認後書き込み成功
)
9.3 バックアップとリストア
# Qdrantスナップショット作成
curl -X POST "http://localhost:6333/collections/articles/snapshots"
# スナップショットリカバリ
curl -X PUT "http://localhost:6333/collections/articles/snapshots/recover" \
-H "Content-Type: application/json" \
-d '{"location": "http://backup-server/snapshot.tar"}'
# pgvector: pg_dump活用
pg_dump -t documents mydb > documents_backup.sql
9.4 モニタリング
monitoring_metrics = {
"検索レイテンシ (p50, p95, p99)": "目標: p99 100ms以下",
"QPS(秒当たりクエリ数)": "負荷に応じてモニタリング",
"Recall@K": "精度。0.95以上を目標",
"インデックスサイズ/メモリ使用量": "OOM防止",
"挿入レイテンシ": "リアルタイム更新時に重要",
"ディスク使用量": "容量計画",
"レプリケーション遅延": "データ一貫性",
}
10. 性能ベンチマーク
10.1 ANNベンチマーク結果(100万ベクトル、128次元)
| DB / アルゴリズム | QPS(Recall 0.95) | QPS(Recall 0.99) | インデックス時間 | メモリ |
|---|---|---|---|---|
| Qdrant HNSW | 8,500 | 4,200 | 12分 | 2.1GB |
| Weaviate HNSW | 7,800 | 3,900 | 14分 | 2.3GB |
| Milvus HNSW | 9,200 | 4,500 | 11分 | 2.0GB |
| pgvector HNSW | 3,400 | 1,600 | 25分 | 2.5GB |
| Pinecone (p2) | 5,000 | 2,800 | N/A | N/A |
| FAISS IVF-PQ | 12,000 | 5,500 | 8分 | 0.4GB |
10.2 実戦ベンチマーク(1000万ベクトル、1536次元)
テスト環境: AWS r6g.2xlarge (8vCPU, 64GB RAM)
Qdrant:
- インデックス構築: 45分
- メモリ: 48GB
- p50レイテンシ: 3ms, p99レイテンシ: 12ms
- QPS: 2,100 (Recall@10 = 0.96)
pgvector (HNSW):
- インデックス構築: 2時間30分
- メモリ: 52GB
- p50レイテンシ: 8ms, p99レイテンシ: 35ms
- QPS: 800 (Recall@10 = 0.95)
Milvus (DiskANN):
- インデックス構築: 35分
- メモリ: 12GB(ディスクベース)
- p50レイテンシ: 5ms, p99レイテンシ: 18ms
- QPS: 1,800 (Recall@10 = 0.95)
10.3 ベンチマーク要約
小規模(10万以下)+ 既存PostgreSQL → pgvector
小規模プロトタイピング → ChromaDB
中規模(10万〜1000万)+ セルフホスティング → QdrantまたはWeaviate
大規模(1000万+)+ セルフホスティング → Milvus
マネージドサービス希望 → PineconeまたはZilliz Cloud
ハイブリッド検索重要 → Weaviate
フィルタリング重要 → Qdrant
11. コスト分析
11.1 マネージドサービスコスト比較
| サービス | 無料ティア | 有料開始価格 | 100万ベクトル推定コスト |
|---|---|---|---|
| Pinecone Serverless | 2GBストレージ | 読み書き課金 | 月約70ドル |
| Pinecone Pod (s1) | - | 月70ドル | 月約140ドル |
| Weaviate Cloud | 14日無料 | 月25ドル | 月約100ドル |
| Qdrant Cloud | 1GB無料 | 月25ドル | 月約65ドル |
| Zilliz Cloud | 無料ティア | 従量制 | 月約90ドル |
11.2 セルフホスティングコスト
100万ベクトル(1536次元、HNSW)推定インフラ:
- RAM必要: 約12GB
- ディスク: 約20GB
- AWS r6g.xlarge (4vCPU, 32GB): 月約150ドル
- 運用人件費別途
1000万ベクトル:
- RAM必要: 約100GB
- AWS r6g.4xlarge (16vCPU, 128GB): 月約600ドル
コスト削減のヒント:
- 量子化でメモリ60〜75%削減
- DiskANNでSSD活用(メモリ80%削減)
- 次元削減(1536 → 512)でメモリ3倍節約
12. クイズ
Q1. コサイン類似度とユークリッド距離の違いは?
コサイン類似度は2つのベクトルの方向(角度) のみを比較します。ベクトルの大きさに関係なく、方向が同じなら1です。ユークリッド距離は2つのベクトル間の直線距離を測定し、ベクトルの大きさも結果に影響します。正規化されたベクトルでは、両メトリクスは同じ順序になります。テキストエンベディングにはコサイン類似度がデフォルト推奨です。
Q2. HNSWアルゴリズムのMパラメータを高くするとどうなりますか?
Mは各ノードの最大接続数です。Mを高くするとグラフがより密になり、検索精度(recall)が向上しますが、メモリ使用量が増加し、インデックス構築時間も長くなります。一般的にM=16がデフォルトで、高いrecallが必要ならM=32〜64に上げられます。非常に高い値は収穫逓減が発生します。
Q3. ハイブリッド検索でのRRF(Reciprocal Rank Fusion)の役割は?
RRFはキーワード検索とベクトル検索の結果をランキングベースで統合するアルゴリズムです。各文書のRRFスコアは1/(k + rank)で計算され、両方の検索結果で高いランクを持つ文書が最終的に上位に来ます。k=60が標準で、スコア正規化が不要という利点があります。
Q4. pgvectorのHNSWインデックスとIVFFlatインデックスのどちらを選ぶべきですか?
HNSWをデフォルト選択として推奨します。HNSWはより高いrecall、より速い検索速度、リアルタイム挿入サポートという利点があります。IVFFlatはメモリ制約が厳しい場合に検討します。IVFFlatはインデックス構築が速くメモリ使用量が少ないですが、データが頻繁に変更される場合は再構築(REINDEX)が必要になる可能性があります。
Q5. 1000万ベクトル規模でのコスト効率的なVector DB選択は?
セルフホスティングが可能なら: QdrantまたはMilvusがコスト効率的です。MilvusのDiskANNインデックスを使用するとメモリを大幅に節約できます。マネージドを希望なら: Pinecone Serverlessが従量制でコスト管理が可能です。量子化(Scalar/Binary)を適用するとメモリを60〜75%削減し、インフラコストを大幅に削減できます。次元削減(1536から512へ)も効果的です。
13. 参考資料(さんこうしりょう)
- Pinecone Documentation - https://docs.pinecone.io/
- Weaviate Documentation - https://weaviate.io/developers/weaviate
- Qdrant Documentation - https://qdrant.tech/documentation/
- Milvus Documentation - https://milvus.io/docs
- pgvector GitHub - https://github.com/pgvector/pgvector
- ChromaDB Documentation - https://docs.trychroma.com/
- ANN Benchmarks - https://ann-benchmarks.com/
- FAISS Wiki - https://github.com/facebookresearch/faiss/wiki
- OpenAI Embeddings Guide - https://platform.openai.com/docs/guides/embeddings
- Cohere Embed Documentation - https://docs.cohere.com/reference/embed
- HNSW原論文 - https://arxiv.org/abs/1603.09320
- Product Quantization論文 - https://hal.inria.fr/inria-00514462v2/document
- MTEB Leaderboard - https://huggingface.co/spaces/mteb/leaderboard
- Reciprocal Rank Fusion論文 - https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf
현재 단락 (1/513)
従来のデータベースは正確なキーワードマッチングに基づいています。「子犬(こいぬ)が公園(こうえん)で遊(あそ)んでいる」で検索すると、「犬(いぬ)が芝生(しばふ)で走(はし)っている」は見つかりません...