在查询 Elasticsearch 时始终返回精确的查询结果数(track_total_hits)

陪她去流浪 桃子 2020年01月09日 阅读次数:4714

Elasticsearch 的较早版本在查询文档数据时,始终会返回查询结果的精确(命中)总数:

GET _search?size=0
{
  "hits": {
    "total": 1267474995831,
    "max_score": 0,
    "hits": []
  }
}

total就是一个标量,直接表明结果的总数。

后来不知道是哪个版本,Elasticsearch 的返回结果不再返回精确的数值了。取而代之的是一个“可能非常模糊”的值 + 实际值与这个值的关系:

GET _search?size=0
{
  "hits" : {
    "total" : {
      "value" : 10000,
      "relation" : "gte"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

total变成了一个对象。value是一个模糊的值,relation是这个精确值与模糊值的关系。 比如这里的意思是表示:大概有10000个查询结果,精确的值比它大于或等于/不少于(gte, greater than or equal to)

如果我们不要求展示精确的结果总数,这样也还行。比如,把结果表示成:不少于 10000 条记录。

按照 Elasticsearch 官网 Track total hits的说法, 返回模糊结果总数的目的纯粹是为了提高性能。

Track total hits

Generally the total hit count can’t be computed accurately without visiting all matches, which is costly for queries that match lots of documents.

The track_total_hits parameter allows you to control how the total number of hits should be tracked. Given that it is often enough to have a lower bound of the number of hits, such as "there are at least 10000 hits", the default is set to 10,000. This means that requests will count the total hit accurately up to 10,000 hits.

It’s is a good trade off to speed up searches if you don’t need the accurate number of hits after a certain threshold.

设置 track_total_hitstrue 即可返回精确的查询结果数:

GET _search?size=0
{
  "track_total_hits": true
}
{
  "hits" : {
    "total" : {
      "value" : 11002,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}

这时候返回了精确的结果数,并且relation始终为eq

更多的细节请参考上面的文档。

更新

2020-10-08: 这天我在优化公司代码时,针对 700 亿的某个聚合,track_total_hitstrue 时反比 false 远远快,这是我完全没有想到的,也没有找到相关解释,目前还是未解之密。所以,小心优化这个可能会让人“误解”的参数?

这篇文章的内容已被作者标记为“过时”/“需要更新”/“不具参考意义”。

标签:ElasticSearch