1. 程式人生 > 其它 >ES分頁查詢速度慢調優

ES分頁查詢速度慢調優

es分頁查詢

方式一:from + size

from + size方式查詢
from表示頁碼
size表示頁面大小
比如from為30,size為100,則要查詢第30頁,展示100條資料
那麼es查詢的方式為獲取到查詢條件(略)下的30 * 100等於3000條資料,然後給你返回最後的100條資料,前面的2900條資料將被過濾掉

而且es是有多個分片的話,將從每個分片去取得相應條件下的資料,然後彙總為3000條,最後返回其中的100條,所以分頁越深,ES處理的開銷就越大,佔用記憶體就越大。
優點
方式簡單,容易上手,針對資料量小的淺分頁,速度可以滿足要求
缺點
深分頁時查詢速度慢,對伺服器記憶體開銷大

方式二:scroll方案

通過scroll方式可以一次性查詢大量的資料,甚至全量資料,我們的第一次查詢(會返回一個scroll_id,使用此scroll_id來查詢下一組size大小的資料),會生成一個當前查詢條件的快照,後面的每次(翻頁)滾屏都是基於這個快照的結果,即使有新的資料進來,也不會影響這個快照的結果.
第一次查詢如下:
POST /kibana_sample_data_ecommerce/_search?scroll=1m
{
    "size": 10,
    "query": {
        "match_all" : {
        }
    }
}
scroll=1m表示很多人對scroll這個引數容易混淆,誤認為是查詢的限制時間。這個理解是錯誤的。這個時間其實指的是es把本次快照的結果快取起來的有效時間。
scroll 引數相當於告訴了ES我們的search context要保持多久,後面每個 scroll 請求都會設定一個新的過期時間,以確保我們可以一直進行下一頁操作。

通過scroll_id去拿資料的時候,可以不用設定index(索引名)跟size(資料大小)資訊,類似如下:
POST /_search/scroll
{
    "scroll" : "1m",
  "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAA5AWNGpKbFNMZnVSc3loXzQwb0tJZHBtZw=="
}
以此類推,後面每次滾屏都把前一個的scroll_id複製過來

為什麼scroll比較塊

ES的檢索分為query(查詢)和fetch(獲取)階段,query階段的效率比較高,只是將滿足條件的文件id彙總起來,fetch階段基於每個分片的結果在coordinating(座標)節點上進行全域性排序,然後最終計算出結果。

scroll查詢的時候,在query階段把符合條件的文件id儲存在 search context(搜尋上下文)中,後面每次scroll分批取出只是根據scroll_id定位到遊標的位置,然後抓取size大小的結果集即可。 
優點
適合實時性要求不高,要查詢大量資料的場景,適合報表匯出等業務或者ES內部的重置索引
缺點
實時性不高,只是往下一頁迭代查詢,不能往回查詢且不能獲取跳頁查詢

方式三:search after方案

search after使用實時遊標來幫我們解決實時滾動的問題,簡單來說前一次查詢的結果會返回一個唯一的字串,下次查詢再帶上這個字串
第一次查詢:
GET /kibana_sample_data_ecommerce/_search
{
  "size" : 2,
  "query": {
    "bool": {
      "must": [
        {"match": {
          "customer_first_name": "Diane"
        }}
      ],
      "filter": {
        "range": {
          "order_date": {
            "gte": "2020-01-03"
          }
        }
      }
    }
  }, 
  "sort": [
    {
      "order_date": "desc",
      "_id": "asc"
      
    }
  ]
}

資料返回結果的最後一條裡面能獲取到order_date與_id
於是我們將使用search after
GET /kibana_sample_data_ecommerce/_search
{
  "size" : 2,
  "query": {
    "bool": {
      "must": [
        {"match": {
          "customer_first_name": "Diane"
        }}
      ],
      "filter": {
        "range": {
          "order_date": {
            "gte": "2020-01-03"
          }
        }
      }
    }
  }, 
  "search_after": 
      [
          1580597280000,
          "RZz1f28BdseAsPClqbyw"
        ],
  "sort": [
    {
      "order_date": "desc",
      "_id": "asc"
      
    }
  ]
}
 "search_after":[1580597280000,"RZz1f28BdseAsPClqbyw"] 說明: search_after數組裡面是多個排序引數,用逗號隔開
當使用search_after引數時,from的值必須被設為0或者-1

實現原理

因為我們search_after傳遞了排序的唯一標識,ES只需從每個分片上拿到滿足條件的文件數量就行了,然後基於這些文件最終聚合成10條結果返回
優點
基於ES內部排序好的遊標,可以實時高效的進行分頁查詢
缺點
只能做下一頁這樣的查詢場景,不能隨機的指定頁數查詢(跳頁)。