如何限制Elasticsearch搜索排名计算范围,避免对全量匹配文档排序
限制Elasticsearch排名计算文档范围的实现方案
默认配置下Elasticsearch会遍历所有匹配查询条件的文档,虽然排序阶段会用优先队列只保留TopN结果,但全量遍历匹配、初步算分比较的过程依然会产生很高开销。要实现最多仅对1000个匹配文档执行排名操作,可以直接用查询级参数实现,不需要调整索引结构:
- 使用
terminate_after查询参数
该参数作用是设置单个分片最多收集多少个匹配文档后,直接终止该分片的匹配、算分流程,不再扫描分片内剩余文档。如果要实现全局最多1000个匹配文档参与排名,先查询索引的主分片数量,用1000除以主分片数,得到的数值就是每个分片的terminate_after阈值。
举个例子,如果你的testIndex有5个主分片,每个分片设置terminate_after=200,全局最多就会收集5*200=1000个匹配文档,后续不会再处理多余文档。对应的查询示例如下:
POST testIndex/_search?size=200&terminate_after=200 { "query": { "query_string": { "query": "(title:QA Manager OR title:QA Lead) AND (skills:JIRA OR skills:Software Development OR skills:Test Case)" } } }
如果分片数据分布不均,最终收集到的总匹配文档数可能略低于1000,但绝对不会超过你设定的全局上限。
- 搭配
track_total_hits参数降低额外开销
默认配置下Elasticsearch会统计全量匹配文档的总条数,这个过程同样会遍历所有匹配项产生开销。你可以把这个参数设置为1000,告诉ES统计到命中数达到1000就停止总数统计,进一步减少资源消耗:
POST testIndex/_search?size=200&terminate_after=200&track_total_hits=1000 { "query": { "query_string": { "query": "(title:QA Manager OR title:QA Lead) AND (skills:JIRA OR skills:Software Development OR skills:Test Case)" } } }
注意事项:
terminate_after属于性能优先的近似优化,最终返回的Top200结果是从截断后的最多1000个匹配文档中选出的,不是全量匹配集的全局Top200,会损失一定结果精度,适合对查询延迟要求高、可接受少量召回损失的业务场景。
内容的提问来源于stack exchange,提问作者Mayank Rupareliya
相关产品推荐
相关产品推荐

