GitHub概要

qdrant/qdrant

Qdrant - High-performance, massive-scale Vector Database and Vector Search Engine for the next generation of AI. Also available in the cloud https://cloud.qdrant.io/

ホームページ:https://qdrant.tech
スター24,978
ウォッチ138
フォーク1,722
作成日:2020年5月30日
言語:Rust
ライセンス:Apache License 2.0

トピックス

ai-searchai-search-engineembeddings-similarityhnswimage-searchknn-algorithmmachine-learningmlopsnearest-neighbor-searchneural-networkneural-searchrecommender-systemsearchsearch-enginesearch-enginessimilarity-searchvector-databasevector-searchvector-search-engine

スター履歴

qdrant/qdrant Star History
データ取得日時: 2025/7/30 00:10

データベース

Qdrant

概要

QdrantはRustで開発された高性能ベクトル検索エンジン・ベクトルデータベースです。高次元ベクトルとそれに付随するJSONペイロードの効率的な格納、検索、管理に特化して設計されています。2025年のベンチマークで最高のRPS(リクエスト毎秒)と最低レイテンシを達成し、パフォーマンスリーダーとして評価されています。ニューラルネットワークベースのマッチング、意味検索、推薦システムなどに最適化されています。

詳細

Qdrantは、Rustの高速性、メモリ安全性、並行性の特徴を最大限に活用し、高負荷下でも安定した動作を実現します。複雑なフィルタリング機能を拡張サポートし、動的クエリプランニングとペイロードインデックスにより、メタデータフィルタリングが必要なアプリケーションに最適です。

Qdrantの主な特徴:

  • Rust実装による高性能: メモリ安全性と低レベル制御により最高速度を実現
  • ベクトル類似性検索: HNSWアルゴリズムによる効率的な最近傍探索
  • ペイロードフィルタリング: JSONメタデータに対する複雑なフィルタリング(キーワード、全文検索、数値範囲、地理的位置)
  • ハイブリッド検索: 密ベクトルと疎ベクトルの両方をサポート
  • 分散アーキテクチャ: シャーディングとレプリケーションによる水平スケーリング
  • 複数インターフェース: REST APIとgRPC APIの両方を提供
  • ベクトル量子化: RAMを最大97%削減し、検索速度と精度のトレードオフを管理
  • オンディスクストレージ: 大規模データセット対応
  • Write-Ahead Logging: データの永続性と更新の確認を保証
  • SIMD最適化: x86-x64とNeonアーキテクチャでのハードウェアアクセラレーション
  • 非同期I/O: io_uringを使用したディスクスループットの最大化
  • バイナリ量子化: 高次元ベクトルの検索パフォーマンスを40倍向上

アーキテクチャ

Qdrantは以下の階層的アーキテクチャを採用:

  1. APIレイヤー: actix-web(REST)とtonic(gRPC)によるエンドポイント
  2. アプリケーションコア: リクエストディスパッチャーとRaftコンセンサス
  3. コレクション管理: メタデータ管理と分散ロジック
  4. データレイヤー: シャードレプリケーションとローカル/リモートシャード
  5. ストレージ&インデックス: セグメント単位のベクトル・ペイロード格納
  6. 永続化レイヤー: WriteAheadLog、RocksDB、メモリマップファイル

2025年の最新動向

  • エッジデバイス向け軽量版の開発
  • カスタムRust製Gridstoreキーバリューストアの導入(RocksDBからの移行)
  • パフォーマンスベンチマークでの業界リーダーシップ
  • 3500万以上の埋め込みを1秒以下でクエリ可能

メリット・デメリット

メリット

  • 最高性能: 2025年ベンチマークで最高RPS・最低レイテンシを達成
  • Rust実装: メモリ安全性と並行性により高速かつ安定
  • 高度なフィルタリング: ペイロードインデックスによる複雑なメタデータフィルタ
  • メモリ効率: ベクトル量子化により最大97%のRAM削減
  • スケーラビリティ: 分散アーキテクチャで大規模展開に対応
  • 開発者体験: シンプルなAPIと豊富なSDK(Python、Go、Java、Node.js、Rust)
  • ハードウェア最適化: SIMD命令による高速ベクトル演算
  • 柔軟な検索: 密・疎ベクトルの両方をサポート
  • オープンソース: Apache 2.0ライセンス

デメリット

  • 学習曲線: ベクトル検索の概念理解が必要
  • Rust専門知識: カスタマイズには Rustの知識が必要
  • リソース消費: 大規模インデックスはメモリを大量消費
  • 限定的なエコシステム: Milvusと比べて統合ツールが少ない
  • エンタープライズ機能: マネージドサービスの選択肢が限定的

主要リンク

書き方の例

インストール・セットアップ

# Docker での実行
docker pull qdrant/qdrant
docker run -p 6333:6333 -p 6334:6334 \
    -v $(pwd)/qdrant_storage:/qdrant/storage:z \
    qdrant/qdrant

# Docker Compose での実行
cat > docker-compose.yml << EOF
version: '3.4'
services:
  qdrant:
    image: qdrant/qdrant
    restart: always
    ports:
      - 6333:6333
      - 6334:6334
    volumes:
      - ./qdrant_storage:/qdrant/storage:z
EOF
docker-compose up -d

# Rustでソースからビルド
git clone https://github.com/qdrant/qdrant.git
cd qdrant
cargo build --release
./target/release/qdrant

# Python クライアントインストール
pip install qdrant-client

# Node.js クライアントインストール
npm install @qdrant/js-client-rest

# Go クライアントインストール
go get -u github.com/qdrant/go-client

基本操作(Python SDK)

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct
import numpy as np

# クライアント初期化
client = QdrantClient("localhost", port=6333)
# または Qdrant Cloud
# client = QdrantClient(url="https://xxx.qdrant.io", api_key="your-api-key")

# コレクション作成
client.create_collection(
    collection_name="my_collection",
    vectors_config=VectorParams(size=768, distance=Distance.COSINE),
)

# ポイント挿入
points = [
    PointStruct(
        id=1,
        vector=np.random.rand(768).tolist(),
        payload={"text": "Qdrantは高性能ベクトルデータベース", "category": "database"}
    ),
    PointStruct(
        id=2,
        vector=np.random.rand(768).tolist(),
        payload={"text": "Rustで実装された検索エンジン", "category": "search"}
    ),
    PointStruct(
        id=3,
        vector=np.random.rand(768).tolist(),
        payload={"text": "2025年パフォーマンスリーダー", "category": "benchmark"}
    )
]

client.upsert(
    collection_name="my_collection",
    points=points
)

# ベクトル検索
query_vector = np.random.rand(768).tolist()
search_result = client.search(
    collection_name="my_collection",
    query_vector=query_vector,
    limit=3
)

for hit in search_result:
    print(f"ID: {hit.id}, Score: {hit.score}, Payload: {hit.payload}")

高度な検索機能

from qdrant_client.models import Filter, FieldCondition, MatchValue, Range

# フィルタリング付き検索
search_result = client.search(
    collection_name="my_collection",
    query_vector=query_vector,
    query_filter=Filter(
        must=[
            FieldCondition(
                key="category",
                match=MatchValue(value="database")
            )
        ]
    ),
    limit=5
)

# 範囲フィルタリング
search_result = client.search(
    collection_name="my_collection",
    query_vector=query_vector,
    query_filter=Filter(
        must=[
            FieldCondition(
                key="price",
                range=Range(
                    gte=100,
                    lte=1000
                )
            )
        ]
    ),
    limit=10
)

# 複数条件の組み合わせ
from qdrant_client.models import MatchAny

search_result = client.search(
    collection_name="products",
    query_vector=query_vector,
    query_filter=Filter(
        must=[
            FieldCondition(
                key="category",
                match=MatchAny(any=["electronics", "computers"])
            )
        ],
        must_not=[
            FieldCondition(
                key="discontinued",
                match=MatchValue(value=True)
            )
        ]
    ),
    limit=20
)

# スコアしきい値付き検索
search_result = client.search(
    collection_name="my_collection",
    query_vector=query_vector,
    score_threshold=0.8,
    limit=10
)

ペイロードインデックスの作成

from qdrant_client.models import PayloadSchemaType

# テキストフィールドのインデックス作成
client.create_payload_index(
    collection_name="my_collection",
    field_name="text",
    field_schema=PayloadSchemaType.TEXT
)

# 数値フィールドのインデックス作成
client.create_payload_index(
    collection_name="my_collection",
    field_name="price",
    field_schema=PayloadSchemaType.FLOAT
)

# キーワードフィールドのインデックス作成
client.create_payload_index(
    collection_name="my_collection",
    field_name="category",
    field_schema=PayloadSchemaType.KEYWORD
)

# 地理的フィールドのインデックス作成
client.create_payload_index(
    collection_name="locations",
    field_name="location",
    field_schema=PayloadSchemaType.GEO
)

バッチ操作と最適化

# バッチ挿入(大量データの効率的な挿入)
batch_size = 100
all_points = []

for i in range(10000):
    point = PointStruct(
        id=i,
        vector=np.random.rand(768).tolist(),
        payload={
            "text": f"Document {i}",
            "category": f"cat_{i % 10}",
            "timestamp": i * 1000
        }
    )
    all_points.append(point)
    
    if len(all_points) >= batch_size:
        client.upsert(
            collection_name="my_collection",
            points=all_points
        )
        all_points = []

# 残りのポイントを挿入
if all_points:
    client.upsert(
        collection_name="my_collection",
        points=all_points
    )

# コレクションの最適化
client.update_collection(
    collection_name="my_collection",
    optimizer_config={
        "deleted_threshold": 0.2,
        "vacuum_min_vector_number": 1000,
        "default_segment_number": 2,
        "max_segment_size": 200000,
        "memmap_threshold": 50000,
        "indexing_threshold": 10000,
        "flush_interval_sec": 5,
        "max_optimization_threads": 2
    }
)

埋め込みモデルとの統合

from sentence_transformers import SentenceTransformer
from qdrant_client.models import Batch

# 埋め込みモデルの初期化
model = SentenceTransformer('all-MiniLM-L6-v2')

# テキストデータ
texts = [
    "Qdrantは高速なベクトル検索エンジンです",
    "Rustで実装されており、高いパフォーマンスを誇ります",
    "複雑なフィルタリングとペイロード管理が可能です"
]

# 埋め込みベクトルの生成
embeddings = model.encode(texts)

# Qdrantへの挿入
points = []
for idx, (text, embedding) in enumerate(zip(texts, embeddings)):
    points.append(
        PointStruct(
            id=idx,
            vector=embedding.tolist(),
            payload={"text": text}
        )
    )

client.upsert(
    collection_name="text_collection",
    points=points
)

# セマンティック検索
query_text = "ベクトルデータベースの性能"
query_embedding = model.encode(query_text)

results = client.search(
    collection_name="text_collection",
    query_vector=query_embedding.tolist(),
    limit=3,
    with_payload=True
)

for result in results:
    print(f"Score: {result.score:.4f}, Text: {result.payload['text']}")

スナップショットとバックアップ

# スナップショットの作成
client.create_snapshot(collection_name="my_collection")

# スナップショット一覧の取得
snapshots = client.list_snapshots(collection_name="my_collection")
for snapshot in snapshots:
    print(f"Snapshot: {snapshot.name}, Created: {snapshot.creation_time}")

# フルバックアップの作成
client.create_full_snapshot()

# スナップショットからの復元
client.recover_snapshot(
    collection_name="my_collection",
    location="http://localhost:6333/collections/my_collection/snapshots/snapshot_2024.snapshot"
)

gRPC APIの使用

from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams

# gRPCクライアントの初期化(より高速)
client = QdrantClient(
    host="localhost",
    port=6334,  # gRPCポート
    grpc_port=6334,
    prefer_grpc=True
)

# 以降の操作は同じ
client.create_collection(
    collection_name="grpc_collection",
    vectors_config=VectorParams(size=384, distance=Distance.DOT),
)

マルチベクトル検索

from qdrant_client.models import NamedVector, VectorParams

# 複数のベクトルを持つコレクション作成
client.create_collection(
    collection_name="multi_vector_collection",
    vectors_config={
        "text": VectorParams(size=768, distance=Distance.COSINE),
        "image": VectorParams(size=512, distance=Distance.EUCLID)
    }
)

# マルチベクトルポイントの挿入
client.upsert(
    collection_name="multi_vector_collection",
    points=[
        PointStruct(
            id=1,
            vector={
                "text": np.random.rand(768).tolist(),
                "image": np.random.rand(512).tolist()
            },
            payload={"description": "製品1"}
        )
    ]
)

# 特定のベクトルで検索
text_results = client.search(
    collection_name="multi_vector_collection",
    query_vector=np.random.rand(768).tolist(),
    using="text",
    limit=5
)

image_results = client.search(
    collection_name="multi_vector_collection",
    query_vector=np.random.rand(512).tolist(),
    using="image",
    limit=5
)

パフォーマンスチューニング

from qdrant_client.models import OptimizersConfigDiff, HnswConfigDiff

# HNSWパラメータの調整
client.update_collection(
    collection_name="my_collection",
    hnsw_config=HnswConfigDiff(
        m=32,  # より多くの接続でより高精度
        ef_construct=200,  # 構築時の精度
        full_scan_threshold=20000  # フルスキャンのしきい値
    )
)

# 検索時のパラメータ
search_result = client.search(
    collection_name="my_collection",
    query_vector=query_vector,
    search_params={
        "hnsw_ef": 128,  # 検索時の精度パラメータ
        "exact": False  # 近似検索を使用
    },
    limit=10
)

# 量子化の設定
from qdrant_client.models import ScalarQuantization, QuantizationSearchParams

client.update_collection(
    collection_name="my_collection",
    quantization_config=ScalarQuantization(
        scalar={
            "type": "int8",
            "quantile": 0.99,
            "always_ram": True
        }
    )
)

# 量子化を使用した検索
search_result = client.search(
    collection_name="my_collection",
    query_vector=query_vector,
    search_params={
        "quantization": QuantizationSearchParams(
            ignore=False,
            rescore=True,
            oversampling=2.0
        )
    },
    limit=10
)