我们有一个如下形式的查询:
{
"query": {
"bool": {
"filter": [
{
"term": {
"userId": {
"value": "a_user_id",
"boost": 1
}
}
},
{
"range": {
"date": {
"from": 1648598400000,
"to": 1648684799999,
"boost": 1
}
}
},
{
"query_string": {
"query": "*MyQuery*",
"fields": [
"aField^1.0",
"anotherField^1.0",
"thirdField^1.0"
],
"boost": 1
}
}
],
"boost": 1
}
}
}
如果我们删除第三个过滤器(query_string
),对于上述查询的不同变体,性能将得到显著提高(通常从大约2000毫秒提高到20毫秒)。
问题是,前两个过滤器(在userId
和date
范围上)总是只会产生少量的搜索命中(比如50个左右)。
因此,如果能够提示Elasticsearch,或者以其他方式影响查询计划,就可以解决我们的问题。
在ES的旧(1.x)版本中,这似乎受过滤器顺序的影响。从Elasticsearch: Order of filters for best performance:
布尔子句中筛选器得顺序对性能很重要.应将特定性更强得筛选器放在特定性较弱得筛选器之前,以便尽早排除尽可能多得文档.如果子句A可以匹配1千万个文档,而子句B只能匹配100个文档,则应将子句B放在子句A之前.
但新版本更智能-https://www.elastic.co/blog/elasticsearch-query-execution-order:
问:我在查询DSL中放置查询/过滤器的顺序是否重要?答:否,因为它们将根据各自的成本和匹配成本自动重新排序。
但是,通过修改ES搜索请求,是否仍有可能达到预期的结果?
1条答案
按热度按时间vxf3dgd41#
您的查询应该如下所示,这样过滤器首先运行,只会选择大约50个文档,然后您的代价高昂的
query_string
(因为前导通配符)将只在这50个文档上运行。