这个坑值得记一笔。Qdrant 1.9.2 上按 source=manual 做 scroll,10 万点耗时 900 毫秒,dashboard 里 source 的索引状态显示绿色,同一个集合的纯向量查询却只要 20 毫秒。
刚开始盯着「过滤值带了首尾空格,规范化后与索引里的值不相等」,折腾了半个多小时,排掉了。
排查方向其实有限,先把可能性排一排。索引建在 payload 子字段上,查询用的是顶层键,路径根本对不上;字段类型建成 integer,实际写入的是字符串,索引命不中;索引刚建完优化器还没跑完,points_count 与已索引数量差很多。
先查集合的 payload 索引定义与点数
curl -s http://127.0.0.1:6333/collections/kb | jq "{payload_schema, points_count}"
随后按实际字段路径重建 keyword 索引
curl -X PUT http://127.0.0.1:6333/collections/kb/index -H "Content-Type: application/json" -d '{"field_name":"source","field_schema":"keyword"}'
接着用带过滤的 count 验证条件能命中
curl -X POST http://127.0.0.1:6333/collections/kb/points/count -H "Content-Type: application/json" -d '{"filter":{"must":[{"key":"source","match":{"value":"manual"}}]},"exact":true}'
末了等优化完成后再看同一字段的索引状态
curl -s http://127.0.0.1:6333/collections/kb | jq ".payload_schema.source"
改完先别撤,确认这几项。count 返回的数量与实际写入条数一致,同样的 scroll 耗时降到 30 毫秒以内,payload_schema 里 source 类型是 keyword。
过滤索引只对带该字段的查询有效,多个 must 条件里缺一个索引就会退化成扫描,建索引时按查询条件清单逐个对。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
