使用ES做搜索引擎拉取數(shù)據(jù)的時候音念,如果數(shù)據(jù)量太大,通過傳統(tǒng)的from + size的方式并不能獲取所有的數(shù)據(jù)(默認(rèn)最大記錄數(shù)10000),因為隨著頁數(shù)的增加,會消耗大量的內(nèi)存者祖,導(dǎo)致ES集群不穩(wěn)定。
ES提供了3中解決深度翻頁的操作绢彤,分別是scroll七问、sliced scroll 和 search after:
scroll
scroll api提供了一個全局深度翻頁的操作, 首次請求會返回一個scroll_id茫舶,使用該scroll_id可以順序獲取下一批次的數(shù)據(jù)械巡;scroll 請求不能用來做用戶端的實時請求,只能用來做線下大量數(shù)據(jù)的翻頁處理,例如數(shù)據(jù)的導(dǎo)出坟比、遷移和_reindex操作,還有同一個scroll_id無法并行處理數(shù)據(jù)嚷往,所以處理完全部的數(shù)據(jù)執(zhí)行時間會稍長一些葛账。
- 例如我們使用scroll翻頁獲取包含elasticsearch的Twitter,那么首次請求的語句如下:
POST /twitter/_search?scroll=1m
{
"size": 100,
"query": {
"match" : {
"title" : "elasticsearch"
}
}
}
其中scroll=1m是指scroll_id保留上下文的時間
- 首次請求會返回一個scroll_id皮仁,我們根據(jù)這個值去不斷拉取下一頁直至沒有結(jié)果返回:
POST /_search/scroll
{
"scroll" : "1m",
"scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
}
針對scroll api下籍琳,同一個scroll_id無法并行處理數(shù)據(jù)的問題,es又推出了sliced scroll贷祈,與scroll api的區(qū)別是sliced scroll可以通過切片的方式指定多scroll并行處理趋急。
sliced scroll
sliced scroll api 除指定上下文保留時間外,還需要指定最大切片和當(dāng)前切片势誊,最大切片數(shù)據(jù)一般和shard數(shù)一致或者小于shard數(shù)呜达,每個切片的scroll操作和scroll api的操作是一致的:
GET /twitter/_search?scroll=1m
{
"slice": {
"id": 0,
"max": 2
},
"query": {
"match" : {
"title" : "elasticsearch"
}
}
}
GET /twitter/_search?scroll=1m
{
"slice": {
"id": 1,
"max": 2
},
"query": {
"match" : {
"title" : "elasticsearch"
}
}
}
因為支持并行處理,執(zhí)行時間要比scroll快很多粟耻。
search after
上面兩種翻頁的方式都無法支撐用戶在線高并發(fā)操作查近,search_after提供了一種動態(tài)指針的方案,即基于上一頁排序值檢索下一頁實現(xiàn)動態(tài)分頁:
- 首次查詢
GET twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "elasticsearch"
}
},
"sort": [
{"date": "asc"},
{"tie_breaker_id": "asc"}
]
}
因為是動態(tài)指針挤忙,所以不需要像scroll api那樣指定上下文保留時間了
- 通過上一頁返回的date + tie_breaker_id最后一個值做為這一頁的search_after:
GET twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "elasticsearch"
}
},
"search_after": [1463538857, "654323"],
"sort": [
{"_score": "desc"},
{"tie_breaker_id": "asc"}
]
}
說白了 search_after 并沒有解決隨機(jī)跳頁查詢的場景霜威,但是可以支撐多query并發(fā)請求;search_after 操作需要指定一個支持排序且值唯一的字段用來做下一頁拉取的指針册烈,這種翻頁方式也可以通過bool查詢的range filter實現(xiàn)戈泼。