Elasticsearch分頁一般有三種方式:
1.form和size的方式
2.Scroll api
3.search_after參數
from+size分頁
按照一般的查詢流程來說,如果我想查詢前10條數據:
1 客戶端請求發給某個節點
2 節點轉發給個個分片,查詢每個分片上的前10條
3 結果返回給節點,整合數據,提取前10條
4 返回給請求客戶端
該分頁方式可以通過from+size的方式來進行實現。
from定義了目標數據的偏移值,size定義當前返回的事件數目。
GET /fs/_search?pretty
{
"from" : 0 , "size" : 10
}
GET /fs/_search?pretty
{
"from" : 10 , "size" : 10
}
這種分頁方式只適合少量數據,因爲隨from增大,查詢的時間就會越大,而且數據量越大,查詢的效率指數下降
優點:from+size在數據量不大的情況下,效率比較高
缺點:在數據量非常大的情況下,from+size分頁會把全部記錄加載到內存中,這樣做不但運行速遞特別慢,而且容易讓es出現內存不足而掛掉
比如要取第5001頁的數據,在分頁的時候,elasticsearch需要首先在每一個節點上取出50020的數據,然後和每一個節點的所有數據進行排序,取出排序後在50010到50020的數據,然後返回。這樣隨着數據量的增大,每次分頁時排序的開銷會越來越大。
一般的分頁需求我們可以使用form和size的方式實現,但是這種分頁方式在深度分頁的場景下應該是要避免使用的。深度分頁會隨着請求的頁次增加,所消耗的內存和時間的增長也是成比例的增加,爲了避免深度分頁產生的問題,elasticsearch從2.0版本開始,增加了一個限制:
index.max_result_window =10000
scroll深分頁
爲了解決上面的問題,elasticsearch提出了一個scroll滾動的方式,這個滾動的方式原理就是通過每次查詢後,返回一個scroll_id。根據這個scroll_id 進行下一頁的查詢。可以把這個scroll_id理解爲通常關係型數據庫中的遊標。
scroll就是維護了當前索引段的一份快照信息–緩存(這個快照信息是你執行這個scroll查詢時的快照)
可以把 scroll 分爲初始化和遍歷兩步:
1、初始化時將所有符合搜索條件的搜索結果緩存起來,可以想象成快照;
GET fs/_search?scroll=3m
{
"query": {"match_all": {}},
"size": 3
}
初始化的時候就像是普通的search一樣
其中的scroll=3m代表當前查詢的數據緩存3分鐘
Size:3 代表當前查詢3條數據
2、遍歷時,從這個快照裏取數據;
在遍歷時候,拿到上一次遍歷中的_scroll_id,然後帶scroll參數,重複上一次的遍歷步驟,直到返回的數據爲空,表示遍歷完成。
每次都要傳參數scroll,刷新搜索結果的緩存時間,另外不需要指定index和type(不要把緩存的時時間設置太長,佔用內存)。
scroll雖然能夠解決from size帶來的問題,但是由於它代表的是某個時刻的snapshot,不適合做實時查詢;且由於scroll後接超時時間,頻繁地發起scroll請求,也會出現一系列問題。
search_after參數
search_after: 性能優秀,類似於優化後的分頁查詢,歷史條件過濾掉數據。
檢索第一頁的查詢如下所示:
POST twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "elasticsearch"
}
},
"sort": [
{"date": "asc"},
{"_id": "desc"}
]
}
每個文檔具有一個唯一值的字段應該用作排序規範的仲裁器。否則,具有相同排序值的文檔的排序順序將是未定義的。建議的方法是使用字段_id,它肯定包含每個文檔的一個唯一值。
上面的請求會爲每一個文檔返回一個包含sort排序值的數組。這些sort排序值可以被用於 search_after 參數裏以便抓取下一頁的數據。比如,我們可以使用最後的一個文檔的sort排序值,將它傳遞給 search_after 參數:
GET twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "elasticsearch"
}
},
"search_after": [1463538857, "654323"],
"sort": [
{"date": "asc"},
{"_id": "desc"}
]
}
當我們使用 search_after 參數的時候,from參數必須被設置成 0 或 -1 (當然你也可以不設置這個from參數)。
search_after缺點是不能夠隨機跳轉分頁,只能是一頁一頁的向後翻,並且需要至少指定一個唯一不重複字段來排序。它與滾動API非常相似,但與它不同,search_after參數是無狀態的,它始終針對最新版本的搜索器進行解析。因此,排序順序可能會在步行期間發生變化,具體取決於索引的更新和刪除。