数据库向量索引:召回率、延迟和写入成本一起算
数据库向量索引:召回率、延迟和写入成本一起算
一、向量索引不是给数据库加一个新字段那么简单
向量检索进入数据库后,很多系统开始把 embedding 当成普通列存储,再加一个近似最近邻索引。表面上看,这是 SQL 能力的扩展;实际上,它会改变存储布局、查询优化、写入放大和资源隔离。向量列通常高维、占空间大、更新成本高,不能按普通 varchar 理解。
评估数据库向量索引时,不能只看单次查询是否能返回相似结果。至少要同时看召回率、P95 延迟、索引构建时间、内存占用、写入吞吐、更新延迟和过滤条件支持。只追求召回率,可能把线上写入拖垮;只追求延迟,可能让结果质量不可接受。
二、查询链路:向量召回还要叠加业务过滤
flowchart TD A[查询向量] --> B[ANN 索引] B --> C[候选 TopK] C --> D[业务过滤] D --> E[精排或重算距离] E --> F[返回结果] G[标量条件] --> D业务过滤是数据库场景的关键差异。很多向量库在纯向量 TopK 上表现不错,但真实查询往往还要按租户、权限、时间、状态和分类过滤。如果过滤发生在向量召回之后,可能出现 TopK 候选被过滤掉大半,最终结果不足;如果过滤前置,又需要索引支持混合查询。
因此评测时要构造混合查询,而不是只跑裸向量搜索。比如同样的 query,在全库、单租户、大租户、小租户、近 7 天数据和某个分类下分别测试。不同过滤条件下,召回率和延迟可能差异很大。
三、实验脚本:记录质量和性能双指标
下面示例展示一个评测结果结构。重点是把质量和性能放在同一张表里。
result = { "index_type": "hnsw", "ef_search": 128, "top_k": 20, "recall_at_10": 0.932, "p95_latency_ms": 38.7, "memory_gb": 14.2, "write_qps": 1200, "filter_mode": "tenant_id + status" }HNSW、IVF、PQ 等索引方案各有取舍。HNSW 通常查询快、召回高,但内存占用和构建成本较高;量化方案能降低存储,但会带来精度损失;倒排分桶适合大规模数据,但参数选择影响明显。没有通吃方案,只有适合当前数据分布和业务约束的方案。
向量归一化和距离度量也要固定。cosine、dot product、L2 的含义不同,embedding 模型训练目标也不同。距离度量选错,索引再快也没有意义。评测报告必须写清楚向量维度、归一化方式和度量函数。
四、运维问题:构建、更新和隔离比查询更难
向量索引构建可能消耗大量 CPU、内存和 IO。在线构建时要限制资源,避免影响普通 SQL。大表重建索引还要考虑失败恢复、进度记录和增量更新。把向量索引当成普通二级索引,通常会在运维阶段吃苦头。
更新也不便宜。文档内容变化后,embedding 需要重新生成,向量索引需要更新。批量更新会造成写入放大和索引碎片。可以采用异步更新和版本字段,但要接受短时间搜索结果滞后。强一致向量检索成本很高,业务必须知道这个事实。
资源隔离同样重要。向量检索是 CPU 和内存密集型任务,不能让它挤占核心交易查询。可以按实例、资源组或队列隔离,并限制单查询 TopK 和并发。数据库支持向量能力,不代表所有业务都能随便扫。
五、总结
数据库向量索引要同时评估召回率、延迟、写入、更新、内存和业务过滤能力。向量列不是普通字段,ANN 索引也不是普通二级索引。把质量指标和系统成本一起算,才能判断它是否适合进入生产。
