如何解決Elasticsearch的深度翻頁問題

使用ES做搜索引擎拉取數(shù)據(jù)的時候,如果數(shù)據(jù)量太大,通過傳統(tǒng)的from + size的方式并不能獲取所有的數(shù)據(jù)(默認最大記錄數(shù)10000),因為隨著頁數(shù)的增加,會消耗大量的內(nèi)存,導致ES集群不穩(wěn)定。

ES提供了3中解決深度翻頁的操作,分別是scroll、sliced scroll 和 search after:

scroll

scroll api提供了一個全局深度翻頁的操作, 首次請求會返回一個scroll_id,使用該scroll_id可以順序獲取下一批次的數(shù)據(jù);scroll 請求不能用來做用戶端的實時請求,只能用來做線下大量數(shù)據(jù)的翻頁處理,例如數(shù)據(jù)的導出、遷移和_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 除指定上下文保留時間外,還需要指定最大切片和當前切片,最大切片數(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 并沒有解決隨機跳頁查詢的場景,但是可以支撐多query并發(fā)請求;search_after 操作需要指定一個支持排序且值唯一的字段用來做下一頁拉取的指針,這種翻頁方式也可以通過bool查詢的range filter實現(xiàn)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容