ES系列之利用filter讓你的查詢效率飛起來

bool查詢簡介

Elasticsearch(下面簡稱ES)中的bool查詢在業務中使用也是比較多的。在一些非實時的分頁查詢,導出的場景,我們經常使用bool查詢組合各種查詢條件。

Bool查詢包括四種子句,

  • must
  • filter
  • should
  • must_not

我這裏只介紹下must和filter兩種子句,因爲是我們今天要講的重點。其它的可以自行查詢官方文檔。

  1. must, 返回的文檔必須滿足must子句的條件,並且參與計算分值
  2. filter, 返回的文檔必須滿足filter子句的條件。但是跟Must不一樣的是,不會計算分值, 並且可以使用緩存

從上面的描述來看,你應該已經知道,如果只看查詢的結果,must和filter是一樣的。區別是場景不一樣。如果結果需要算分就使用must,否則可以考慮使用filter。

光說比較抽象,看個例子,下面兩個語句,查詢的結果是一樣的。

使用filter過濾時間範圍,

GET kibana_sample_data_ecommerce/_search
{
  "size": 1000, 
  "query": {
    "bool": {
      "must": [
        {"term": {
          "currency": "EUR"
        }}
      ],
      "filter": {
        "range": {
          "order_date": {
            "gte": "2020-01-25T23:45:36.000+00:00",
            "lte": "2020-02-01T23:45:36.000+00:00"
          }
        }
      }
    }
  }
}

使用must過濾時間範圍,

GET kibana_sample_data_ecommerce/_search
{
  "size": 1000, 
  "query": {
    "bool": {
      "must": [
        {"term": {
          "currency": "EUR"
        }},
        {"range": {
          "order_date": {
            "gte": "2020-01-25T23:45:36.000+00:00",
            "lte": "2020-02-01T23:45:36.000+00:00"
          }
        }}
      ]
    }
  }
}

查詢的結果都是,

{
  "took" : 25,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1087,
      "relation" : "eq"
    },
    
    ...

filter比較高效的原理

上一節你已經知道了must和filter的基本用法和區別。簡單來講,如果你的業務場景不需要算分,使用filter可以真的讓你的查詢效率飛起來。

爲了說明filter查詢高效的原因,我們需要引入ES的一個概念 query contextfilter context

query context

query context關注的是,文檔到底有多匹配查詢的條件,這個匹配的程度是由相關性分數決定的,分數越高自然就越匹配。所以這種查詢除了關注文檔是否滿足查詢條件,還需要額外的計算相關性分數.

filter context

filter context關注的是,文檔是否匹配查詢條件,結果只有兩個,是和否。沒有其它額外的計算。它常用的一個場景就是過濾時間範圍。

並且filter context會自動被ES緩存結果,效率進一步提高。

對於bool查詢,must使用的就是query context,而filter使用的就是filter context

我們可以通過一個示例驗證下。繼續使用第一節的例子,我們通過kibana自帶的search profiler來看看ES的查詢的詳細過程。

使用must查詢的執行過程是這樣的:

在這裏插入圖片描述

在這裏插入圖片描述

可以明顯看到,此次查詢計算了相關性分數,而且score的部分佔據了查詢時間的10分之一左右。

filter的查詢我就不截圖了,區別就是score這部分是0,也就是不計算相關性分數。

除了是否計算相關性算分的差別,經常使用的過濾器將被Elasticsearch自動緩存,以提高性能。

我自己曾經在一個項目中,對一個業務查詢場景做了這種優化,當時線上的索引文檔數量大概是3000萬左右,改成filter之後,查詢的速度幾乎快了一倍。

我截了幾張圖,你來感受下。

在這裏插入圖片描述

在這裏插入圖片描述
可以看到時間整個縮短了一半。

總結

我們應該根據自己的實際業務場景選擇合適的查詢語句,在某些不需要相關性算分的查詢場景,儘量使用filter context可以讓你的查詢更加高效。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章