内容提要
Qdrant v1.17.1 新增 prevent_unoptimized 优化器设置,用于解决批量上传后未索引段导致的搜索延迟。启用后,新点暂缓搜索直至段优化完成,数据仍持久化。测试显示优化时间从 88 秒降至 0.6 秒,查询延迟基本不变,但搜索结果暂时减少、召回率下降,复制集上点可能闪烁。适合写量小、优化快的集合。
延伸解读
与 indexed_only 的路径差异
文章指出,Qdrant v1.17 及之前,解决未索引段搜索延迟的方案是读路径上的 indexed_only 参数,它让搜索跳过未优化段。而 v1.17.1 新增的 prevent_unoptimized 则作用于写路径,将新点暂存至段优化完成。两者机制不同:前者在查询时过滤,后者在写入时延迟。理解这一区别有助于根据场景选择合适方案。
启用后的召回率代价
prevent_unoptimized 会暂缓搜索未优化段中的点,导致搜索结果暂时减少,召回率下降,且最近写入的数据无法立即被检索到。在复制集上,延迟点在不同副本上可见时间不一致,可能造成同一查询结果闪烁。文章强调,这种召回损失在优化时间短的集合中可接受,但在大集合中可能让用户长时间看到部分结果,需权衡写入量和段大小。
性能提升与适用边界
在 10 万点、768 维的测试中,启用 prevent_unoptimized 后优化时间从 88.1 秒降至 0.56 秒,查询延迟和吞吐量基本不变。优化加速是因为优化器不再与扫描大未索引段的搜索竞争资源。但文章提醒,这并非总是更优:它适合写入量小、优化快的集合;若集合大、优化慢,则可能长期牺牲召回率,需谨慎评估。
复制集下的读亲和性建议
在复制集上使用 prevent_unoptimized 时,延迟点会在不同副本上以略微不同的时间变为可见,导致连续请求可能看到点出现、消失又出现。文章建议通过 X-Qdrant-Route-Affinity 头将客户端读取固定到单个副本,以避免这种闪烁现象。这一细节对于多副本部署的稳定性很重要,需在启用该设置时一并考虑。
Q&A
Qdrant v1.17.1 的 prevent_unoptimized 设置是做什么的?
prevent_unoptimized 是 Qdrant v1.17.1 新增的实验性优化器设置,用于解决批量上传后未索引段导致的搜索延迟。启用后,新点暂缓搜索直至段优化完成,数据仍持久化。
prevent_unoptimized 和 indexed_only 有什么区别?
indexed_only 是读路径的修复,搜索时只查已优化段,跳过未索引段,但点可能闪烁;prevent_unoptimized 是写路径的修复,新点写入优化中的段时暂缓搜索,直到段优化完成。
启用 prevent_unoptimized 后,优化时间和查询延迟有什么变化?
测试显示,优化时间从 88.1 秒降至 0.56 秒,查询延迟基本不变(p50 0.117s vs 0.120s,p95 0.187s vs 0.193s,p99 0.206s vs 0.209s),吞吐量也相近。
使用 prevent_unoptimized 时,上传数据需要注意什么?
上传时应设置 wait=False,否则每个 upsert 调用会阻塞直到点可见(即段优化完成),导致批量上传循环停滞甚至客户端超时。Rust/Go SDK 和 REST API 默认 wait=False,不受影响。
prevent_unoptimized 有哪些缺点或风险?
启用后,搜索会暂时返回较少结果,召回率下降,且最近写入的数据不会立即显示。在复制集上,点可能在不同副本间闪烁。适合写量小、优化快的集合,大集合可能导致长时间部分结果。
如何监控 prevent_unoptimized 的优化进度?
可以通过 get_collection 查看 deferred_points 数量,通过 get_optimizations 查看运行中和排队的优化任务,直到两者都清空。也可以直接 GET /collections/{collection_name}/optimizations 或读取 .update_queue.deferred_points。