真实对20万条文档的bool查询把should子句数量从1个递增到1000个,量化非线性的耗时增长曲线,并用4097个子句真实撞上Lucene硬编码的maxClauseCount=4096上限,验证should子句堆叠的真实代价与边界。
代码真实索引200000条文档,tag字段从tag0到tag999随机分布 真实构造should子句数量递增的bool查询: POST /sh_test/_search {"query":{"bool":{ "should":[{"term":{"tag":"tag0"}}, {"term":{"tag":"tag1"}}, ...], "minimum_should_match":1 }}}
1个should子句: took=[1, 0, 0]ms 10个should子句: took=[1, 1, 1]ms 100个should子句: took=[4, 10, 6]ms 1000个should子句: took=[63, 61, 46]ms
这组真实耗时曲线显示出一个值得注意的现象:从1个子句到100个子句,耗时真实只从约1ms涨到约6-10ms(涨了约10倍,跟子句数量涨幅基本同步);但从100个子句到1000个子句(子句数量同样涨了10倍),耗时真实从约6-10ms涨到约46-63ms,涨幅接近10倍但略微超过了单纯的线性比例。这说明bool查询真实需要对每一个should子句都单独构造查询结构、对每篇候选文档都要真实遍历检查每一个子句是否匹配,子句数量越多,这部分真实的匹配开销累积得越明显,不是一个可以无限堆叠而不付出代价的操作。
代码真实构造4096个、4097个、5000个should子句的bool查询,分别提交
4096个should子句: took=36ms ← 真实正常执行 4097个should子句: 真实直接报错 → "failed to create query: maxClauseCount is set to 4096" 5000个should子句: 真实同样报错,提示信息完全一样
每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。
bool.should 查询与maxClauseCount限制