論文概要(Abstract)
本論文は、ベクトルデータベース管理システム(Vector DBMS)を体系的にサーベイした包括的な研究です。近年のLLM・RAGパイプラインの普及に伴い急増するベクトル検索需要に対し、ストレージ管理・インデックス構造・クエリ処理・システムアーキテクチャの4軸で主要なベクトルDBを分類・比較しています。pgvector、Milvus、Qdrant、Pinecone、Weaviate、Chroma等を同一基準で評価し、HNSW・IVF・PQ等のANNアルゴリズムの性能特性を実測データとともに整理しています。
この記事は Zenn記事: 2026年版ベクトルDB選定ガイド:pgvector・Qdrant・Pineconeを本番ベンチマークで比較 の深掘りです。
情報源
- arXiv ID: 2401.08801
- URL: https://arxiv.org/abs/2401.08801
- 著者: James Jie Pan, Jianguo Wang, Guoliang Li
- 発表年: 2024
- 分野: cs.DB, cs.AI
背景と動機(Background & Motivation)
大規模言語モデル(LLM)とRetrieval-Augmented Generation(RAG)の急速な普及により、高次元ベクトルデータを効率的に格納・検索するシステムの需要が爆発的に増加しています。従来のリレーショナルDBでは、数百〜数千次元のベクトルに対するコサイン類似度やL2距離に基づく近傍検索を効率的に処理できません。
この課題に対し、専用ベクトルDB(Milvus、Qdrant)、既存DB拡張(pgvector、Elasticsearch)、マネージドサービス(Pinecone)といった多様なアプローチが登場しましたが、各システムの設計思想・性能特性・トレードオフを統一的に整理した研究は限られていました。本論文はこのギャップを埋める初の包括的サーベイです。
主要な貢献(Key Contributions)
- 統一的な分類フレームワーク: ベクトルDBを「ストレージ管理」「インデックス構造」「クエリ処理」「システムアーキテクチャ」の4軸で体系的に分類
- ANNアルゴリズムの比較分析: HNSW、IVF、PQ(Product Quantization)、DiskANN等の主要アルゴリズムをRecall-QPS-メモリ使用量の3指標で比較
- 実測ベンチマーク: SIFT1M(128次元、100万件)、GloVe-100、Deep1Bなどの標準データセットでの性能比較データを集約
- 設計トレードオフの明確化: インメモリ vs ディスクベース、単一ノード vs 分散、静的 vs 動的データの各軸でのトレードオフを体系化
技術的詳細(Technical Details)
ベクトルDBの4層アーキテクチャ
本論文はベクトルDBを以下の4層で分析しています。
Layer 1: ストレージ管理
ベクトルデータの格納方式には大きく3つのアプローチがあります。
インメモリ格納: すべてのベクトルをRAM上に保持。QdrantやMilvus(メモリモード)が採用。最高のレイテンシ性能を実現できますが、データ量がメモリ容量に制約されます。
ディスクベース格納: SSD上にベクトルを格納し、メモリにはインデックスのみを保持。DiskANNが代表的です。10億件規模のデータを64GB程度のメモリで処理可能ですが、SSDのランダムアクセス性能に依存します。
ハイブリッド格納: pgvectorやWeaviateが採用するアプローチ。頻繁にアクセスされるベクトルをメモリにキャッシュし、残りはディスクに格納します。
Layer 2: インデックス構造
ANNアルゴリズムは性能特性が大きく異なります。
HNSW(Hierarchical Navigable Small World):
グラフベースのインデックスで、現在最も広く使われています。多層グラフ構造を構築し、上位層で粗い近傍探索、下位層で精密な探索を行います。
構築時の計算量は以下の通りです:
\[O(N \cdot M \cdot \log N)\]ここで、
- $N$: データ数
- $M$: グラフの最大次数(エッジ数)。典型値は16〜64
検索時の計算量は:
\[O(M \cdot \log N \cdot ef)\]- $ef$: 検索時の探索幅。大きいほどRecallが向上するがレイテンシが増加
HNSWの主要パラメータと推奨値:
| パラメータ | 意味 | 推奨値 | 影響 |
|---|---|---|---|
| $M$ | グラフ次数 | 16〜64 | メモリ使用量とRecallのトレードオフ |
| $ef_construction$ | 構築時の探索幅 | 100〜200 | 構築時間とインデックス品質 |
| $ef_search$ | 検索時の探索幅 | 50〜200 | レイテンシとRecallのトレードオフ |
IVF(Inverted File Index):
ベクトル空間をk-meansクラスタリングで$C$個のセルに分割し、クエリに近いセルのみを探索します。
\[\text{Recall} \approx 1 - \left(1 - \frac{n\_probe}{C}\right)^k\]- $C$: クラスタ数(典型値: $\sqrt{N}$)
- $n_probe$: 探索するクラスタ数
IVFの利点はメモリ効率の良さですが、高次元データではクラスタ境界付近のベクトルで精度が低下します。
PQ(Product Quantization):
高次元ベクトルを低次元のサブベクトルに分割し、各サブベクトルをコードブックで量子化します。
\[\mathbf{x} \approx [q_1(\mathbf{x}^{(1)}), q_2(\mathbf{x}^{(2)}), \ldots, q_m(\mathbf{x}^{(m)})]\]- $\mathbf{x}^{(i)}$: $i$番目のサブベクトル($D/m$次元)
- $q_i$: $i$番目のサブ量子化器($k$個のセントロイド)
- メモリ削減率: $D \times 4$ bytes → $m \times \lceil\log_2 k\rceil$ bits
768次元ベクトルの場合、PQにより元のfloat32表現(3072 bytes)を96 bytes程度まで圧縮できます(32倍の圧縮)。
Layer 3: クエリ処理
フィルタ付きベクトル検索は、実務で最も重要な機能の一つです。メタデータ条件(例: category = "tech", date >= "2024-01-01")とベクトル類似度を組み合わせた検索です。
処理戦略は3つあります:
- Pre-filtering: メタデータフィルタを先に適用し、残ったベクトルに対してANN検索。フィルタ比率が小さい場合に非効率
- Post-filtering: ANN検索の結果にメタデータフィルタを適用。Recallが低下するリスク
- In-filter search: ANNアルゴリズム内でフィルタを統合。Qdrantが採用するFilterable HNSWが代表例
Layer 4: システムアーキテクチャ
スタンドアロン型: pgvector(PostgreSQL拡張)、Chroma。既存DBに統合されるため運用コストが低い 分散型: Milvus、Qdrant(クラスタモード)。シャーディングとレプリケーションでスケールアウト サーバーレス型: Pinecone。インフラ管理が不要だが、ベンダーロックインのリスク
主要DBの機能比較
| 機能 | pgvector | Qdrant | Milvus | Pinecone | Weaviate |
|---|---|---|---|---|---|
| ANN | HNSW, IVFFlat | HNSW | HNSW, IVF, DiskANN | 独自 | HNSW |
| フィルタ | WHERE句 | Filterable HNSW | 属性フィルタ | メタデータフィルタ | BM25+Dense |
| 分散 | リードレプリカ | ネイティブ | ネイティブ | サーバーレス | ネイティブ |
| ストレージ | ディスク+キャッシュ | メモリ+mmap | メモリ/ディスク | マネージド | メモリ+ディスク |
| 言語 | C | Rust | Go/C++ | - | Go |
| ライセンス | PostgreSQL | Apache 2.0 | Apache 2.0 | プロプライエタリ | BSD-3 |
実装のポイント(Implementation)
HNSWパラメータチューニングの実践
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# pgvector でのHNSWインデックス作成例
# M=16: メモリ使用量を抑えつつ高いRecallを維持するバランスポイント
# ef_construction=200: 構築に時間をかけてインデックス品質を向上
import psycopg
from pgvector.psycopg import register_vector
conn = psycopg.connect("postgresql://user:pass@localhost/mydb")
register_vector(conn)
# HNSW インデックス作成
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_docs_hnsw
ON documents USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 200)
""")
# 検索時のefパラメータ設定(セッション単位)
conn.execute("SET hnsw.ef_search = 100")
# コサイン類似度検索
query_vec = get_embedding("検索クエリ")
results = conn.execute(
"SELECT id, content, 1 - (embedding <=> %s::vector) AS similarity "
"FROM documents ORDER BY embedding <=> %s::vector LIMIT 10",
[query_vec, query_vec],
).fetchall()
Qdrant でのフィルタ付き検索
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from qdrant_client import QdrantClient
from qdrant_client.models import (
Filter, FieldCondition, MatchValue, Range
)
client = QdrantClient(host="localhost", port=6333)
# Filterable HNSW: フィルタとANNを同時に処理
results = client.query_points(
collection_name="documents",
query=get_embedding("検索クエリ"),
query_filter=Filter(
must=[
FieldCondition(
key="category",
match=MatchValue(value="tech")
),
FieldCondition(
key="published_at",
range=Range(gte="2024-01-01")
),
]
),
limit=10,
with_payload=True,
)
Recall-QPS トレードオフの可視化
Recall@10とQPSのトレードオフは、ANNアルゴリズムとパラメータ選択に大きく依存します。
| 設定 | Recall@10 | QPS | メモリ(GB) | 用途 |
|---|---|---|---|---|
| HNSW (M=16, ef=50) | 0.92 | 2,500 | 4.2 | リアルタイム検索 |
| HNSW (M=32, ef=100) | 0.97 | 1,200 | 7.8 | 高精度検索 |
| HNSW (M=64, ef=200) | 0.99 | 450 | 15.2 | 最高精度 |
| IVF (C=1024, nprobe=16) | 0.85 | 5,000 | 1.8 | 高スループット |
| IVFPQ (C=1024, m=32) | 0.78 | 8,000 | 0.6 | メモリ制約環境 |
Production Deployment Guide
AWS実装パターン(コスト最適化重視)
トラフィック量別の推奨構成:
| 規模 | 月間リクエスト | 推奨構成 | 月額コスト | 主要サービス |
|---|---|---|---|---|
| Small | ~3,000 (100/日) | Serverless | $50-150 | Lambda + Bedrock + DynamoDB |
| Medium | ~30,000 (1,000/日) | Hybrid | $300-800 | ECS Fargate + Aurora pgvector |
| Large | 300,000+ (10,000/日) | Container | $2,000-5,000 | EKS + Qdrant Cluster + ElastiCache |
Small構成の詳細(月額$50-150):
- Aurora Serverless v2 (PostgreSQL 16 + pgvector): 0.5〜1 ACU ($43/月)
- Lambda: 検索API、1GB RAM ($20/月)
- API Gateway: REST API ($5/月)
- CloudWatch: 基本監視 ($5/月)
Medium構成の詳細(月額$300-800):
- Aurora PostgreSQL r6g.large + pgvector: 2 vCPU, 16GB RAM ($200/月)
- ECS Fargate: 検索サービス 0.5 vCPU, 1GB RAM × 2タスク ($120/月)
- ElastiCache Redis (cache.t3.micro): クエリキャッシュ ($15/月)
- Application Load Balancer: ($20/月)
Large構成の詳細(月額$2,000-5,000):
- EKS: コントロールプレーン ($72/月)
- Qdrant on EC2 Spot (r6i.xlarge × 3): 分散クラスタ ($600/月、Spot 70%割引適用)
- Aurora PostgreSQL r6g.2xlarge: メタデータ格納 ($400/月)
- ElastiCache Redis (cache.r6g.large): ベクトルキャッシュ ($200/月)
- EC2 Spot Instances (Karpenter管理): 推論ワーカー ($800/月)
コスト削減テクニック:
- Spot Instances使用で最大90%削減(EKS + Karpenter管理)
- Aurora Serverless v2でアイドル時に自動スケールダウン
- ElastiCacheでホットクエリをキャッシュし、DB負荷を80%削減
- Savings Plans (1年コミット)で最大72%削減
コスト試算の注意事項:
- 上記は2026年2月時点のAWS ap-northeast-1(東京)リージョン料金に基づく概算値です
- 実際のコストはトラフィックパターン、ベクトル次元数、データ量により変動します
- 最新料金は AWS料金計算ツール で確認してください
Terraformインフラコード
Small構成 (Serverless): Aurora pgvector + Lambda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# --- VPC基盤 ---
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "vectordb-vpc"
cidr = "10.0.0.0/16"
azs = ["ap-northeast-1a", "ap-northeast-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24"]
database_subnets = ["10.0.3.0/24", "10.0.4.0/24"]
enable_nat_gateway = false
enable_dns_hostnames = true
}
# --- Aurora Serverless v2 (pgvector) ---
resource "aws_rds_cluster" "vectordb" {
cluster_identifier = "vectordb-cluster"
engine = "aurora-postgresql"
engine_version = "16.4"
engine_mode = "provisioned"
database_name = "vectordb"
master_username = "dbadmin"
master_password = aws_secretsmanager_secret_version.db_password.secret_string
db_subnet_group_name = aws_db_subnet_group.vectordb.name
vpc_security_group_ids = [aws_security_group.aurora.id]
serverlessv2_scaling_configuration {
min_capacity = 0.5
max_capacity = 4.0
}
storage_encrypted = true
}
resource "aws_rds_cluster_instance" "vectordb" {
cluster_identifier = aws_rds_cluster.vectordb.id
instance_class = "db.serverless"
engine = aws_rds_cluster.vectordb.engine
engine_version = aws_rds_cluster.vectordb.engine_version
}
# --- Lambda関数 ---
resource "aws_lambda_function" "vector_search" {
filename = "lambda.zip"
function_name = "vector-search-handler"
role = aws_iam_role.lambda_role.arn
handler = "index.handler"
runtime = "python3.12"
timeout = 30
memory_size = 1024
environment {
variables = {
DB_HOST = aws_rds_cluster.vectordb.endpoint
DB_NAME = "vectordb"
DB_SECRET_ARN = aws_secretsmanager_secret.db_password.arn
}
}
vpc_config {
subnet_ids = module.vpc.private_subnets
security_group_ids = [aws_security_group.lambda.id]
}
}
# --- CloudWatch アラーム ---
resource "aws_cloudwatch_metric_alarm" "aurora_cpu" {
alarm_name = "aurora-cpu-high"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = 2
metric_name = "CPUUtilization"
namespace = "AWS/RDS"
period = 300
statistic = "Average"
threshold = 80
alarm_description = "Aurora CPU使用率80%超過"
dimensions = {
DBClusterIdentifier = aws_rds_cluster.vectordb.cluster_identifier
}
}
Large構成 (Container): EKS + Qdrant Cluster
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# --- EKSクラスタ ---
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 20.0"
cluster_name = "vectordb-cluster"
cluster_version = "1.31"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
cluster_endpoint_public_access = true
enable_cluster_creator_admin_permissions = true
}
# --- Karpenter (Spot優先) ---
resource "kubectl_manifest" "karpenter_nodepool" {
yaml_body = <<-YAML
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
name: qdrant-nodes
spec:
template:
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["spot", "on-demand"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["r6i.xlarge", "r6i.2xlarge", "r7i.xlarge"]
nodeClassRef:
name: default
limits:
cpu: "64"
memory: "256Gi"
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 30s
YAML
}
# --- AWS Budgets ---
resource "aws_budgets_budget" "vectordb" {
name = "vectordb-monthly"
budget_type = "COST"
limit_amount = "5000"
limit_unit = "USD"
time_unit = "MONTHLY"
notification {
comparison_operator = "GREATER_THAN"
threshold = 80
threshold_type = "PERCENTAGE"
notification_type = "ACTUAL"
subscriber_email_addresses = ["ops@example.com"]
}
}
セキュリティベストプラクティス
- ネットワーク: Aurora/Qdrantはプライベートサブネットに配置、VPCエンドポイント経由でアクセス
- 認証: IAM認証 + Secrets Manager、環境変数へのハードコード禁止
- 暗号化: Aurora KMS暗号化(保管時)、TLS 1.3(転送時)
- 監査: CloudTrail全リージョン有効化、Config変更追跡
運用・監視設定
1
2
3
4
-- CloudWatch Logs Insights: ベクトル検索レイテンシ分析
fields @timestamp, query_vector_dim, recall, latency_ms
| stats pct(latency_ms, 95) as p95, pct(latency_ms, 99) as p99 by bin(5m)
| filter latency_ms > 100
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import boto3
cloudwatch = boto3.client('cloudwatch')
# Aurora pgvector 検索レイテンシアラート
cloudwatch.put_metric_alarm(
AlarmName='vectordb-search-latency-p99',
ComparisonOperator='GreaterThanThreshold',
EvaluationPeriods=2,
MetricName='ReadLatency',
Namespace='AWS/RDS',
Period=300,
Statistic='p99',
Threshold=0.1, # 100ms
AlarmDescription='ベクトル検索p99レイテンシ100ms超過'
)
コスト最適化チェックリスト
- ~100 req/日 → Aurora Serverless v2 + Lambda ($50-150/月)
- ~1,000 req/日 → Aurora Provisioned + ECS Fargate ($300-800/月)
- 10,000+ req/日 → EKS + Qdrant Cluster + Spot ($2,000-5,000/月)
- EC2 Spot Instances優先(Karpenter自動管理で最大90%削減)
- Aurora Serverless v2でアイドル時0.5 ACUまでスケールダウン
- ElastiCacheでホットクエリキャッシュ(DB負荷80%削減)
- Reserved Instances 1年コミット(72%削減)
- Savings Plans検討(柔軟性重視の場合)
- pgvectorのef_searchを用途別に調整(リアルタイム: 50、バッチ: 200)
- IVFFlat→HNSWへの移行でRecall向上(メモリ増の代わり)
- PQ(Product Quantization)でメモリ使用量を1/4〜1/32に圧縮
- 不要なインデックスの定期的な削除
- CloudWatch Anomaly Detectionでコスト異常の自動検知
- タグ戦略: env/project/teamでコスト可視化
- 開発環境のAurora Serverlessは夜間0 ACUに自動スケールダウン
- S3へのベクトルバックアップにライフサイクルポリシー設定(30日でGlacier)
- VPCエンドポイント使用でNAT Gateway通信料を削減
- Lambda Provisioned Concurrencyは不要なら無効化
- データパーティショニングで検索対象を絞り込み(日付・カテゴリ別)
- ベクトル次元数の最適化(1536→768次元への次元削減でコスト半減)
実験結果(Results)
本論文で集約されたベンチマーク結果を要約します。
SIFT1M(128次元、100万件)での比較
| インデックス | Recall@10 | QPS | メモリ(GB) | ビルド時間 |
|---|---|---|---|---|
| HNSW (M=16) | 0.97 | 1,800 | 0.8 | 45秒 |
| IVFFlat (C=256) | 0.89 | 3,200 | 0.5 | 12秒 |
| IVFPQ (C=256, m=16) | 0.72 | 6,500 | 0.15 | 30秒 |
高次元データ(768次元、100万件)での影響
次元数の増加により、すべてのアルゴリズムでQPSが低下しますが、HNSWの低下率が最も小さく、高次元でも安定した性能を維持します。IVFは次元数に比例して精度が低下する傾向があります。
実運用への応用(Practical Applications)
Zenn記事で紹介した「ステージ別選定フレームワーク」は、本論文の分類と整合しています。
MVPフェーズ(〜1Mベクトル): pgvectorが最適。既存PostgreSQLスタックにCREATE EXTENSION vectorを追加するだけで開始できます。HNSWインデックスにより、100万件程度であれば数百QPS以上の性能が得られます。
成長フェーズ(1M〜10M): フィルタ付き検索の要件が増える段階。QdrantのFilterable HNSWが真価を発揮します。Rust実装によるメモリ効率の良さも、この規模で重要になります。
大規模フェーズ(10M+): Milvusの分散アーキテクチャが適合。シャーディングとレプリケーションにより、水平スケーリングが可能です。
関連研究(Related Work)
- ANN-Benchmarks (Aumüller et al., 2020): ANNアルゴリズムの標準ベンチマークフレームワーク。本論文はこれを拡張し、ベクトルDB全体を評価対象としている
- Milvus: A Purpose-Built Vector Data Management System (Wang et al., 2021): Milvusの設計論文。本サーベイでは他DBとの比較文脈で引用
- Efficient and Robust Approximate Nearest Neighbor Search (Fu et al., 2019): NSGグラフベースANNの提案。HNSWとの性能比較が本論文でも参照
まとめと今後の展望
本論文は、ベクトルDB選定の際の意思決定を体系化する重要な参考文献です。HNSW・IVF・PQ等のANNアルゴリズムの特性理解と、各DBの設計思想(スタンドアロン/分散/サーバーレス)の把握が、適切な選定の鍵となります。
今後の研究方向として、動的データに対するインデックス更新の効率化、フィルタ付き検索の最適化、マルチモーダルベクトル(テキスト+画像+音声)の統合検索が挙げられています。
参考文献
- arXiv: https://arxiv.org/abs/2401.08801
- ANN-Benchmarks: https://ann-benchmarks.com/
- Related Zenn article: https://zenn.dev/0h_n0/articles/8c8bb192985b64