列表查询带六个 term 条件全写在 must 里,took 稳定 780ms。把其中五个挪到 filter 后,同样的数据量降到 90ms,返回条数没变。日志里能对上时间点,这种反而好排。
must 里的子句参与算分,每条命中文档都要算相关性,结果也不进 filter cache。filter 只判断命中与否,结果能缓存成位图,重复查询直接复用。算分本身就不是免费的操作。这一点先确认清楚,后面就不用反复试。
GET orders/_search
{"query": {"bool": {"must": [{"match": {"title": "耳机"}}],
"filter": [{"term": {"status": 1}}, {"term": {"tenant_id": 8}}]}}}
这次卡住的地方就在「filter 查询缓存」这一环,单独把它拎出来验证,别和其他改动混在同一次发布里。偶发问题先统计频率,一小时几次和一天一次,查法完全不同。
改完顺手把文档补一句,省得下次自己重新推一遍。监控和日志的时间要对上,时区不一致会多绕很大一圈。
处理上按这个顺序:不影响排序的条件全部放进 filter;must 只留真正参与相关度的一个条件;别用 constant_score 把整个 bool 包住 反而丢掉缓存;改完对比 profile 里的重写和缓存命中。
结果对不对很好判断,took 从 780ms 降到 100ms 以内,profile 里 filter 子句显示缓存命中。
