深色模式
Qdrant / Weaviate 实战
摘要:本文面向要在自托管场景落地向量库的工程师,对比两款主流开源向量数据库——Rust 写的 Qdrant(重性能/过滤)与 Go 写的 Weaviate(重模块化 AI 管线/混合检索)。给出两者可复制的 Docker 部署、量化压缩、遍历期过滤、混合检索、快照备份与多租户配置,并标出版本相关与未实测项。覆盖版本:Qdrant 1.11+、Weaviate 1.25/1.26。注意各参数随版本变化,以官方文档为准(访问日期 2026-10-09)。
核心概念:两条不同的设计路线
| 维度 | Qdrant | Weaviate |
|---|---|---|
| 语言 | Rust(SIMD + Gridstore) | Go |
| 过滤模型 | 遍历期过滤(traversal-time) | 预过滤 / 异步索引 |
| 模块化 AI | 无内置 vectorizer,embedding 自管 | 内置 text2vec/generative/qna 模块 |
| 量化 | 标量/乘积/二进制(最高 ~64x) | 标量/乘积(PQ/BCQ,版本相关) |
| 多租户 | 集合/分片 | 原生 multi-tenancy(v1.23+) |
| 索引 | HNSW(默认) | HNSW / Flat / Dynamic / HFresh |
一句话选型
要极致性能 + 复杂过滤选 Qdrant;要数据库内做 embedding/rerank/生成选 Weaviate。Qdrant 把过滤做在 HNSW 遍历中,避免「先召回后过滤」的召回损失(来源:qdrant.tech、aicoolies Qdrant 评测,访问 2026-10-09)。
架构与原理
Qdrant 的关键区别:过滤发生在图遍历过程内,候选在相似度比较前已被 payload 条件收窄;Weaviate 的卖点是把 embedding、rerank、生成作为模块织进查询路径,省掉独立微服务。
生产实践一:Qdrant 部署 + 量化
bash
# 单节点(钉版本,勿用 latest)[版本相关]
docker run -d --name qdrant -p 6333:6333 -p 6334:6334 \
-v qdrant_storage:/qdrant/storage \
qdrant/qdrant:v1.11.31
2
3
4
2
3
4
带二进制量化(内存 ~1/16,厂商口径 [未实测])建集合:
python
# pip install qdrant-client
from qdrant_client import QdrantClient
from qdrant_client.http.models import (
Distance, VectorParams, BinaryQuantization, QuantizationConfig, HnswConfigDiff,
)
client = QdrantClient("localhost", port=6333)
client.create_collection(
collection_name="kb_v1",
vectors_config=VectorParams(size=768, distance=Distance.COSINE),
quantization_config=QuantizationConfig(
binary=BinaryQuantization(always_ram=True) # 量化向量常驻 RAM 保低延迟
),
hnsw_config=HnswConfigDiff(m=16, ef_construct=200, full_scan_threshold=10000),
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
遍历期过滤 + 检索(hnsw_ef 即查询期候选宽度):
python
from qdrant_client.http.models import Filter, FieldCondition, MatchValue
client.upsert("kb_v1", points=[/* PointStruct(id, vector, payload) */])
hits = client.search(
collection_name="kb_v1",
query_vector=query_vec,
limit=10,
search_params={"hnsw_ef": 128}, # 查询期可调,召回↔延迟
query_filter=Filter(must=[FieldCondition(key="tenant", match=MatchValue(value="t-001"))]),
)1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
二进制量化依赖归一化
Qdrant 二进制量化对已归一化向量表现最好(OpenAI text-embedding-3 系列已归一化);未归一化 embedding 需先归一化,否则召回下降。量化后用全精度向量做 rescore 可回补精度(来源:qdrant DeepWiki 量化章节、johal war story,访问 2026-10-09)。换 embedding 模型后必须重新量化。
生产实践二:Weaviate 部署 + 混合检索
bash
# 关匿名访问、开持久化、多架构镜像 [版本相关]
docker run -d --name weaviate \
-p 8080:8080 -p 50051:50051 \
-e QUERY_DEFAULTS_LIMIT=25 \
-e AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED='false' \
-e PERSISTENCE_DATA_PATH=/var/lib/weaviate \
-e DEFAULT_VECTORIZER_MODULE=none \
-e CLUSTER_HOSTNAME=node1 \
-v weaviate_data:/var/lib/weaviate \
semitechnologies/weaviate:1.25.41
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Python v4 客户端建类 + HNSW + 混合检索(BM25 + vector,alpha 混合):
python
# pip install weaviate-client
import weaviate
from weaviate.classes.config import Configure, DataType, Property
client = weaviate.connect_to_local() # 单客户端实例复用,勿每请求新建(见故障排查)
if not client.collections.exists("DevDoc"):
client.collections.create(
name="DevDoc",
vectorizer_config=Configure.Vectorizer.none(), # 自带 embedding 时关闭内置
properties=[Property(name="title", data_type=DataType.TEXT)],
vector_index_config=Configure.VectorIndex.hnsw(distance_metric="cosine"),
)
# 混合检索:alpha=0.5 表示 vector/BM25 各半
coll = client.collections.get("DevDoc")
resp = coll.query.hybrid(
query="how to authenticate API",
alpha=0.5,
limit=10,
filters=coll.filter.by_property("tenant") == "t-001", # 租户隔离
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Weaviate 索引族选择
Weaviate 不止 HNSW:Flat(小租户省内存)、Dynamic(v1.25+ 实验,先 Flat 超阈值自动升 HNSW,默认 1 万对象,单向不可降级)、HFresh(大内存受限场景,centroid 驻内存、posting 1-bit 量化落盘)。多租户 SaaS 优先 Dynamic 避免给空租户预建全图(来源:datastudios Weaviate 架构,访问 2026-10-09,版本相关)。
验证
bash
# Qdrant
curl -s http://localhost:6333/health
curl -s http://localhost:6333/collections/kb_v1
# Weaviate
curl -s http://localhost:8080/v1/.well-known/ready
curl -s http://localhost:8080/v1/meta # 期望返回 {"version":"1.25.4"}1
2
3
4
5
6
2
3
4
5
6
python
# Qdrant 验证过滤有效性:用越权 tenant 查询应无结果
hits_bad = client.search("kb_v1", query_vector=query_vec,
query_filter=Filter(must=[FieldCondition(key="tenant", match=MatchValue(value="other")])))
assert len(hits_bad) == 0, "租户隔离失效!"1
2
3
4
2
3
4
回滚与清理
重建集合/类 = 数据丢失
改向量维度、换量化类型、改索引结构都需重建集合。先快照(见下),再新建 kb_v2 双写,确认无问题切读。Qdrant 单节点恢复快照须 --force-snapshot(见 ops.md)。
bash
# Qdrant 清理(不可逆)
# docker exec qdrant qdrant-client 或 REST DELETE /collections/kb_v11
2
2
故障排查
- Weaviate UNAVAILABLE 频发:Python v4 客户端每请求
connect_to_custom新建 gRPC channel,耗尽 HTTP/2 并发流(默认每连接 100)→ 客户端进程级单例复用(来源:markaicode Weaviate Docker stack,访问 2026-10-09)。这是客户端集成错,不是容量上限。 - ARM64 exec format 错误:拉了 amd64-only 镜像 → 用
cr.weaviate.io/semitechnologies/weaviate:<tag>多架构标签,目标架构先测。 - 首跑权限错误:bind mount 目录属主为 root 而容器非 root UID → 改用 named volume 避免属主冲突。
- Qdrant 召回掉:换 embedding 模型未重量化 → CI 校验模型变更须同步量化配置。
- 过滤后无结果:payload 字段名/类型不匹配 → 检查 filter key 与写入 payload 一致。
安全与合规
- 关匿名访问:Weaviate 生产
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=false并配 API key / OIDC;Qdrant 配 API key 或 mTLS。 - 租户隔离:两类库都必须在查询层带租户过滤/命名空间,语义召回不等同鉴权。
- 数据驻留:自托管让数据留在自有基础设施,满足强合规;备份落 S3 须加密与访问收敛(见 ops.md)。
- 多租户:Weaviate 原生 multi-tenancy 适合 SaaS;Qdrant 用集合/分片隔离,配合 RBAC。
成本与性能
量级参考,非实测。
- Qdrant 内存:二进制量化厂商称最高 ~64x 压缩、标量 ~4x、乘积居中;rescore 用全精度回算保精度(来源:qdrant.tech、DeepWiki,访问 2026-10-09)。实测请以你数据为准。
- Weaviate 成本:模块(embedding/生成)拉高算力,单节点成本通常高于 Qdrant;换来少搭一个服务(来源:echoesofthemachine,访问 2026-10-09)。
- 延迟:Qdrant 量化向量常驻 RAM 时检索常 < 20ms(示例口径);Weaviate 混合检索 alpha 调优影响延迟与质量。
- GPU:两者主要靠 CPU 检索;embedding 推理侧可选 GPU。