mcpField
V
vector-database-ops

vector-database-ops

github.com/bagelholeデータ・データベース1.2k312 回インストール23 週間前に更新
リポジトリ

vector-database-ops について

vector-database-opsは、AI検索、RAG、レコメンデーション向けのベクトルデータベース運用スキルです。エンジニアによる製品比較から、デプロイ、インデックス管理、保守、運用環境の調整までを支援します。

主な機能

  1. 01Qdrant、Weaviate、pgvector、Pinecone、Chromaの比較
  2. 02Qdrant、pgvector、Weaviateのデプロイ
  3. 03コレクションとインデックスの管理
  4. 04テナント分離フィルター検索の設定
  5. 05バックアップ、復元、クエリ性能の調整

活用シーン

  1. 01セマンティック検索やRAG用データベースの選定
  2. 02コレクションとデータ移行の管理
  3. 03本番クエリ向けインデックスの調整
  4. 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 のどちらを選ぶか決める前に、実際のクエリパターンでベンチマークを実施します。
  • 一括削除や移行を行う前に、必ずスナップショットを作成します。

関連スキル

コメント