Filtered Query和Post Filter如何选择
在Elasicsearch的官网文档中:(http://www.elastic.co/guide/en/elasticsearch/guide/current/_filtered_query.html),介绍了两种查询方式,一个是Filtered Query,一个是Post Filter。前者是先使用filter,过滤后的结果再query;后者是先query,query的结果再过滤。而在es中,filter的操作使用了cache,速度比query快,因而官网文档提出了一个关于性能的警告(翻译如下): 只有当你需要对搜索结果和聚合使用不同的过滤方式时才考虑使用Post_filter。有时一些用户会直接在常规搜索中使用Post_filter。不要这样做!Post_filter会在查询之后才会被执行,因此会失去过滤在性能上帮助(比如缓存)。Post_filter应该只和聚合一起使用,并且仅当你使用了不同的过滤条件时。
- 测试一 查询条件:
boolFilter.must(FilterBuilders.termFilter("appId", "R6Z7Ews31c8O4BTidZaWyA"))
目标数:10010077hits,测试结果如下(耗时:ms):
Filtered Query | Post Filter |
---|---|
176880 | 171064 |
161548 | 152789 |
164953 | 174562 |
150026 | 155928 |
177425 | 159847 |
结果分析:对单个查询条件共10010077条目标的查询测试。两者对比发现消耗的时间有大有小,不稳定。且由于Filtered Query第一次查询是没有cache的,该次消耗时间偏大。
- 测试二 查询条件:
boolFilter.must(FilterBuilders.termFilter("appId", "R6Z7Ews31c8O4BTidZaWyA"));
boolFilter.should(FilterBuilders.termFilter("province", "上海"))
.should(FilterBuilders.termFilter("province", "山西"))
.should(FilterBuilders.regexpFilter("city", "14.*"))
.should(FilterBuilders.regexpFilter("city", "3307.*"))
.should(FilterBuilders.regexpFilter("city", "40.*"));
目标数:9010477hits,测试结果(单位:ms):
Post Filter | Filtered Query |
---|---|
157410 | 141416 |
159537 | 149571 |
151644 | 145090 |
151364 | 155600 |
结果分析:此次使用了较为复杂的正则查询,且组合了多种条件。但目标总数与上次差不多,结果对比发现Filtered Query的查询平均速度看起来比使用Post Filter 快了一点但仍不稳定,不能稳定的重现。
- 测试三 查询条件:
boolFilter.must(FilterBuilders.termFilter("appId", "R6Z7Ews31c8O4BTidZaWyA"))
.should(FilterBuilders.termFilter("province", "北京"));
目标数:999599hits,测试结果(单位:ms):
Post Filter | Filtered Query |
---|---|
24631 | 19260 |
25485 | 21232 |
25206 | 20373 |
23271 | 19046 |
结果分析:此次尝试缩小样本量,发现Filtered Query能明显的比Post Filter查询快。快了4、5秒左右,且较为稳定。
- 测试四 查询条件:
boolFilter.must(FilterBuilders.termFilter("appId", "R6Z7Ews31c8O4BTidZaWyA"))
.should(FilterBuilders.termFilter("province", "山西"));
目标数:11073hits,测试结果(单位:ms):
Post Filter | Filtered Query |
---|---|
1883 | 547 |
1563 | 563 |
1660 | 499 |
1612 | 604 |
结果分析:此次样本量缩小至1w+,发现FilteredQuery性能优势更加明显了,比PostFilter快了2到3倍。
- 测试五 查询条件:
boolFilter.must(FilterBuilders.termFilter("appId", "R6Z7Ews31c8O4BTidZaWyA"))
.should(FilterBuilders.termFilter("city", "404"));
目标数:1003hits,测试结果(单位:ms):
Post Filter | Filtered Query |
---|---|
1616 | 279 |
1304 | 277 |
1657 | 302 |
1339 | 296 |
结果分析:此次的目标量只有1003条,两者方式的性能对比最明显,Filtered Query的搜索速度5倍左右于Post Filter 。