vector-database-ops について
vector-database-opsは、AI検索、RAG、レコメンデーション向けのベクトルデータベース運用スキルです。エンジニアによる製品比較から、デプロイ、インデックス管理、保守、運用環境の調整までを支援します。
主な機能
- 01Qdrant、Weaviate、pgvector、Pinecone、Chromaの比較
- 02Qdrant、pgvector、Weaviateのデプロイ
- 03コレクションとインデックスの管理
- 04テナント分離フィルター検索の設定
- 05バックアップ、復元、クエリ性能の調整
活用シーン
- 01セマンティック検索やRAG用データベースの選定
- 02コレクションとデータ移行の管理
- 03本番クエリ向けインデックスの調整
- 04ベクトル検索でのテナントデータ分離
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill vector-database-opsインストール後、Claude Code で/vector-database-opsを入力して読み込まれたか確認します。
詳細
ベクトルデータベースの運用
AI を活用した検索、RAG、レコメンデーションシステム向けに、本番環境のベクトルデータベースを運用します。
このスキルを使う場面
次のような場合に、このスキルを使用します。
- RAG またはセマンティック検索アプリケーション向けにベクトルデータベースをセットアップする
- Qdrant、Weaviate、pgvector、Pinecone の中から選ぶ
- コレクション、インデックス、データ移行を管理する
- 本番環境の負荷に合わせて、クエリのパフォーマンスとインデックス作成を最適化する
- 名前空間を分離して、マルチテナントのベクトル検索を実装する
ベクトルデータベースの比較
| データベース | 最適な用途 | ホスティング | フィルタリング | スケーラビリティ |
|---|---|---|---|---|
| Qdrant | 高性能、柔軟なフィルタリング、セルフホスト | セルフホスト/クラウド | 優れている | 非常に高い |
| Weaviate | スキーマファースト、ハイブリッド検索、マルチモーダル | セルフホスト/クラウド | 良好 | 高い |
| pgvector | すでに Postgres を使用している場合、シンプルなユースケース | セルフホスト | 良好 | 中程度 |
| Pinecone | 運用管理不要のマネージドサービス、サーバーレス | マネージドのみ | 良好 | 非常に高い |
| Chroma | ローカル開発、プロトタイピング | セルフホストのみ | 基本的 | 低〜中程度 |
Qdrant — 本番環境へのデプロイ
# Docker (single node)
docker run -d \
--name qdrant \
-p 6333:6333 \
-p 6334:6334 \
-v $(pwd)/qdrant-data:/qdrant/storage \
qdrant/qdrant:latest
# With custom config
docker run -d \
--name qdrant \
-p 6333:6333 \
-v $(pwd)/qdrant-data:/qdrant/storage \
-v $(pwd)/qdrant-config.yaml:/qdrant/config/production.yaml \
qdrant/qdrant:latest
# qdrant-config.yaml
storage:
storage_path: /qdrant/storage
on_disk_payload: true # store payload on disk (saves RAM)
service:
max_request_size_mb: 32
hnsw_index:
m: 16 # graph connections per node
ef_construct: 100 # accuracy vs build time trade-off
full_scan_threshold: 10000 # switch to brute force below this
quantization:
scalar:
type: int8
quantile: 0.99
always_ram: true # keep quantized index in RAM
telemetry_disabled: true
Qdrant のコレクション管理
from qdrant_client import QdrantClient
from qdrant_client.models import (
Distance, VectorParams, HnswConfigDiff,
ScalarQuantizationConfig, ScalarType, QuantizationConfig
)
client = QdrantClient("http://localhost:6333")
# Create optimized collection
client.create_collection(
collection_name="documents",
vectors_config=VectorParams(
size=1536, # OpenAI ada-002 / text-embedding-3-small
distance=Distance.COSINE,
on_disk=True, # save RAM — vectors stored on disk
),
hnsw_config=HnswConfigDiff(
m=32, # higher = better recall, more RAM
ef_construct=200,
on_disk=False, # keep HNSW graph in RAM for speed
),
quantization_config=QuantizationConfig(
scalar=ScalarQuantizationConfig(
type=ScalarType.INT8,
quantile=0.99,
always_ram=True,
)
),
)
# Create payload index for fast filtering
client.create_payload_index(
collection_name="documents",
field_name="tenant_id",
field_schema="keyword",
)
client.create_payload_index(
collection_name="documents",
field_name="created_at",
field_schema="datetime",
)
# Collection info
info = client.get_collection("documents")
print(f"Vectors: {info.vectors_count}, Status: {info.status}")
Qdrant のフィルタリング検索
from qdrant_client.models import Filter, FieldCondition, MatchValue, Range
# Tenant-isolated search (multi-tenant RAG)
results = client.query_points(
collection_name="documents",
query=query_embedding,
query_filter=Filter(
must=[
FieldCondition(key="tenant_id", match=MatchValue(value="acme-corp")),
FieldCondition(key="doc_type", match=MatchValue(value="contract")),
],
should=[
FieldCondition(key="created_at", range=Range(gte="2024-01-01")),
],
),
limit=10,
with_payload=True,
)
pgvector — PostgreSQL 拡張機能
-- Enable extension
CREATE EXTENSION IF NOT EXISTS vector;
-- Create table with vector column
CREATE TABLE documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
content TEXT NOT NULL,
embedding VECTOR(1536),
metadata JSONB DEFAULT '{}',
tenant_id TEXT NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Create HNSW index (faster queries, more memory)
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Create IVFFlat index (less memory, slower build)
-- CREATE INDEX ON documents
-- USING ivfflat (embedding vector_cosine_ops)
-- WITH (lists = 100);
-- Semantic search with metadata filtering
SELECT id, content, metadata,
1 - (embedding <=> $1::vector) AS similarity
FROM documents
WHERE tenant_id = 'acme-corp'
AND metadata->>'doc_type' = 'contract'
ORDER BY embedding <=> $1::vector
LIMIT 10;
# Deploy pgvector via Docker
docker run -d \
--name pgvector \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_DB=vectordb \
-p 5432:5432 \
-v pgvector-data:/var/lib/postgresql/data \
pgvector/pgvector:pg16
Weaviate のデプロイ
# docker-compose for Weaviate
services:
weaviate:
image: semitechnologies/weaviate:latest
ports:
- "8080:8080"
- "50051:50051"
environment:
QUERY_DEFAULTS_LIMIT: 25
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: "false"
AUTHENTICATION_APIKEY_ENABLED: "true"
AUTHENTICATION_APIKEY_ALLOWED_KEYS: "${WEAVIATE_API_KEY}"
AUTHENTICATION_APIKEY_USERS: "admin"
PERSISTENCE_DATA_PATH: /var/lib/weaviate
ENABLE_MODULES: text2vec-openai,generative-openai
OPENAI_APIKEY: "${OPENAI_API_KEY}"
CLUSTER_HOSTNAME: node1
volumes:
- weaviate-data:/var/lib/weaviate
restart: unless-stopped
volumes:
weaviate-data:
バックアップと復元
# Qdrant — snapshot backup
curl -X POST "http://localhost:6333/collections/documents/snapshots"
# Download snapshot
curl -O "http://localhost:6333/collections/documents/snapshots/documents-snapshot.snapshot"
# Restore
curl -X POST "http://localhost:6333/collections/documents/snapshots/recover" \
-H "Content-Type: application/json" \
-d '{"location": "/qdrant/snapshots/documents-snapshot.snapshot"}'
# pgvector — standard pg_dump
pg_dump -h localhost -U postgres -d vectordb \
--table=documents --format=custom > documents-backup.dump
# Restore
pg_restore -h localhost -U postgres -d vectordb documents-backup.dump
パフォーマンスのチューニング
# Qdrant — optimize collection after bulk load
client.update_collection(
collection_name="documents",
optimizer_config={"indexing_threshold": 0}, # force indexing now
)
# Wait for optimization to complete
import time
while True:
info = client.get_collection("documents")
if info.status.value == "green":
break
time.sleep(5)
print(f"Optimizing... segments: {info.segments_count}")
よくある問題
| 問題 | 原因 | 解決策 |
|---|---|---|
| クエリが遅い | HNSW インデックスがまだ作成されていない | インデックス作成を待ち、status == green を確認します |
| RAM 使用量が多い | ベクトルがメモリ上にある | ベクトルに on_disk=True を設定します |
| 再現率が低い | 検索パラメーター ef の値が低い | 検索リクエストの ef を増やします(クエリ実行時) |
| pgvector が遅い | VACUUM せずに IVFFlat を使用している | VACUUM ANALYZE documents を実行します |
| Weaviate の OOM | オブジェクトが多すぎる | 非同期インデックス作成を有効にし、ヒープを増やします |
ベストプラクティス
- 正規化された埋め込みにはコサイン距離、正規化されていない埋め込みには内積を使用します。
- フィルターフィールド(
tenant_id、doc_type)には必ずペイロードインデックスを作成します。 - 1,000 万件を超えるベクトルを含むデータセットでは、
on_diskベクトルとalways_ram量子化を使用します。 - IVFFlat と HNSW のどちらを選ぶか決める前に、実際のクエリパターンでベンチマークを実施します。
- 一括削除や移行を行う前に、必ずスナップショットを作成します。
関連スキル
- RAG インフラストラクチャ - RAG パイプライン全体
- データベース - データベースの一般的な管理
- PostgreSQL - pgvector のホストデータベース運用
コメント
Markdown 対応