天天看點

Elasticsearch7.x DSL文法之分頁查詢

程式員小強總結的 ElasticSearch專題超全總結篇在這裡:傳送門

結合官網資料,做了更詳細的實際使用總結。

從單機版安裝到叢集高可用生産環境搭建、基本概念(索引,分片,節點,反向索引…)、DSL文法實踐、分詞器(内置+中文)、SpringBoot整合實戰、仿京東商品搜尋實戰實作。

1.簡單分頁

對于非深度分頁,簡單查詢時,一般使用from和size進行分頁查詢

  • “from”: 分頁起始位置
  • “size”: 每頁資料大小

1.1寫法

GET /student_info/_search
{
  "query": {
    "match_all": {}
  },
  "from": 1,
  "size": 2
}
           

常見問題:深分頁問題,效率會很低,盡量避免深分頁。

1.2深度分頁問題

ES對于from+size的個數也是有限制的,預設限制二者之和不能超過1w。超過後會報錯,

使用

index.max_result_window:10000

作為保護措施,雖然這個參數可以修改,也可以在配置檔案配置。

但是最好不要這麼做,當所請求的資料總量大于1w時,應用ES遊标(scroll查詢)來代替from+size。如果需要深度分頁對伺服器壓力會變大。如果确認需要設定,則需要提前預估啟動記憶體大小。

Elasticsearch7.x DSL文法之分頁查詢

深分頁舉例

  • 比如每頁100條,當要查詢第100頁也就是9900 ~ 10000資料時,若是去5個節點查詢,那麼每個節點查到這個區間的資料,然後彙總并排序後再取9900 ~ 10000之間的資料,非常消耗資源,而且有OOM的風險。

2.遊标查詢(scoll)

scoll 遊标查詢,指定 scroll=時間 ,指定儲存的分鐘數,

第一次發起請求放回的是資料+_scroll_id ,後面通過 _scroll_id 去請求資料,适合大批量查詢。

#遊标查詢-年齡> 18,每頁2條,儲存1分鐘
GET /student_info/_search?scroll=1m
{
  "query": {
    "range": {
      "age":{
        "gt": 18
      }
    }
  },
  "size": 2
}
           
Elasticsearch7.x DSL文法之分頁查詢

遊标查詢,其實是在 es 裡面緩存了結果 ,然後一次一次的去取,是以發起第一次請求的時候隻有 size ,沒有from,後面的請求隻有 scroll_id 和 scroll 時間

GET /_search/scroll
{
    "scroll": "1m",
    "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAABZxIWYzcxTVZWN1BRd1NpUzg4WHg1RkYzZw=="
}
           
Elasticsearch7.x DSL文法之分頁查詢
Elasticsearch7.x DSL文法之分頁查詢

3.search_after分頁

  • from + size的分頁方式雖然是最靈活的分頁方式,但當分頁深度達到一定程度将會産生深度分頁的問題。
  • scroll能夠解決深度分頁的問題,但是其無法實作實時查詢,即當scroll_id生成後無法查詢到之後資料的變更,因為其底層原理是生成資料的快照。
  • ES-5.X之後 search_after應運而生

使用search_after必須添加排序"sort"條件

如下示例:指定了根據ID升序,年齡倒叙,2個排序條件,search_after中[起始ID,起始年齡]

GET /student_info/_search
{
  "query": {
    "match_all": {}
  },
  "search_after": [
    11000,20
  ],
  "size": 2,
   "sort": [
        {"_id": "asc"},
        {"age": "desc"}
    ]
}
           

請求第一頁的時候,會傳回sort 值,下一頁的時候,把上一頁 sort的值帶入查詢參數 search_after中

Elasticsearch7.x DSL文法之分頁查詢
Elasticsearch7.x DSL文法之分頁查詢

4.三種分頁方式比較

分頁方式 性能 優點 缺點 使用場景
from + size 靈活性好,實作簡單 深度分頁問題 資料量比較小,能容忍深度分頁問題
scroll 解決了深度分頁問題 無法反應資料的實時性維護成本高,需要維護一個 scroll_id跳頁查詢問題 海量資料的導出需要查詢海量結果集的資料
search_after 性能最好不存在深度分頁問題能夠反映資料的實時變更 實作複雜,需要有一個全局唯一的字段連續分頁的實作相對複雜,因為每一次查詢都需要上次查詢的結果跳頁查詢問題 海量資料的分頁

5.總結**

  • Scroll 被推薦用于深度查詢,但是代價是昂貴的,不推薦用于實時使用者請求,而更适用于背景批處理任務,比如非實時導出或群發。
  • search_after 提供了實時的光标來避免深度分頁的問題,其實作方式是使用前一頁的結果來幫助檢索下一頁。
  • search_after不能自由跳到一個随機頁面,隻能按照 sort values 跳轉到下一頁,需要使用一個唯一值的字段作為排序字段,推薦使用_id 作為唯一值的排序字段

繼續閱讀