ElasticSearch?深度分頁(yè)示例解析
1 前言
ElasticSearch 是一個(gè)實(shí)時(shí)的分布式搜索與分析引擎,常用于大量非結(jié)構(gòu)化數(shù)據(jù)的存儲(chǔ)和快速檢索場(chǎng)景,具有很強(qiáng)的擴(kuò)展性??v使其有諸多優(yōu)點(diǎn),在搜索領(lǐng)域遠(yuǎn)超關(guān)系型數(shù)據(jù)庫(kù),但依然存在與關(guān)系型數(shù)據(jù)庫(kù)同樣的深度分頁(yè)問(wèn)題,本文就此問(wèn)題做一個(gè)實(shí)踐性分析探討
2 from + size 分頁(yè)方式
from + size 分頁(yè)方式是 ES 最基本的分頁(yè)方式,類似于關(guān)系型數(shù)據(jù)庫(kù)中的 limit 方式。from 參數(shù)表示:分頁(yè)起始位置;size 參數(shù)表示:每頁(yè)獲取數(shù)據(jù)條數(shù)。例如:
GET /wms_order_sku/_search
{
"query": {
"match_all": {}
},
"from": 10,
"size": 20
}
該條 DSL 語(yǔ)句表示從搜索結(jié)果中第 10 條數(shù)據(jù)位置開始,取之后的 20 條數(shù)據(jù)作為結(jié)果返回。這種分頁(yè)方式在 ES 集群內(nèi)部是如何執(zhí)行的呢?在 ES 中,搜索一般包括 2 個(gè)階段,Query 階段和 Fetch 階段,Query 階段主要確定要獲取哪些 doc,也就是返回所要獲取 doc 的 id 集合,F(xiàn)etch 階段主要通過(guò) id 獲取具體的 doc。
2.1 Query 階段
如上圖所示,Query 階段大致分為 3 步:
- 第一步:Client 發(fā)送查詢請(qǐng)求到 Server 端,Node1 接收到請(qǐng)求然后創(chuàng)建一個(gè)大小為 from + size 的優(yōu)先級(jí)隊(duì)列用來(lái)存放結(jié)果,此時(shí) Node1 被稱為 coordinating node(協(xié)調(diào)節(jié)點(diǎn));
- 第二步:Node1 將請(qǐng)求廣播到涉及的 shard 上,每個(gè) shard 內(nèi)部執(zhí)行搜索請(qǐng)求,然后將執(zhí)行結(jié)果存到自己內(nèi)部的大小同樣為 from+size 的優(yōu)先級(jí)隊(duì)列里;
- 第三步:每個(gè) shard 將暫存的自身優(yōu)先級(jí)隊(duì)列里的結(jié)果返給 Node1,Node1 拿到所有 shard 返回的結(jié)果后,對(duì)結(jié)果進(jìn)行一次合并,產(chǎn)生一個(gè)全局的優(yōu)先級(jí)隊(duì)列,存在 Node1 的優(yōu)先級(jí)隊(duì)列中。(如上圖中,Node1 會(huì)拿到 (from + size) * 6 條數(shù)據(jù),這些數(shù)據(jù)只包含 doc 的唯一標(biāo)識(shí)_id 和用于排序的_score,然后 Node1 會(huì)對(duì)這些數(shù)據(jù)合并排序,選擇前 from + size 條數(shù)據(jù)存到優(yōu)先級(jí)隊(duì)列);
2.2 Fetch 階段
如上圖所示,當(dāng) Query 階段結(jié)束后立馬進(jìn)入 Fetch 階段,F(xiàn)etch 階段也分為 3 步:
- 第一步:Node1 根據(jù)剛才合并后保存在優(yōu)先級(jí)隊(duì)列中的 from+size 條數(shù)據(jù)的 id 集合,發(fā)送請(qǐng)求到對(duì)應(yīng)的 shard 上查詢 doc 數(shù)據(jù)詳情;
- 第二步:各 shard 接收到查詢請(qǐng)求后,查詢到對(duì)應(yīng)的數(shù)據(jù)詳情并返回為 Node1;(Node1 中的優(yōu)先級(jí)隊(duì)列中保存了 from + size 條數(shù)據(jù)的_id,但是在 Fetch 階段并不需要取回所有數(shù)據(jù),只需要取回從 from 到 from + size 之間的 size 條數(shù)據(jù)詳情即可,這 size 條數(shù)據(jù)可能在同一個(gè) shard 也可能在不同的 shard,因此 Node1 使用 multi-get 來(lái)提高性能)
- 第三步:Node1 獲取到對(duì)應(yīng)的分頁(yè)數(shù)據(jù)后,返回給 Client;
2.3 ES 示例
依據(jù)上述我們對(duì) from + size 分頁(yè)方式兩階段的分析會(huì)發(fā)現(xiàn),假如起始位置 from 或者頁(yè)條數(shù) size 特別大時(shí),對(duì)于數(shù)據(jù)查詢和 coordinating node 結(jié)果合并都是巨大的性能損耗。例如:索引 wms_order_sku 有 1 億數(shù)據(jù),分 10 個(gè) shard 存儲(chǔ),當(dāng)一個(gè)請(qǐng)求的 from = 1000000, size = 10。在 Query 階段,每個(gè) shard 就需要返回 1000010 條數(shù)據(jù)的_id 和_score 信息,而 coordinating node 就需要接收 10 * 1000010 條數(shù)據(jù),拿到這些數(shù)據(jù)后需要進(jìn)行全局排序取到前 1000010 條數(shù)據(jù)的_id 集合保存到 coordinating node 的優(yōu)先級(jí)隊(duì)列中,后續(xù)在 Fetch 階段再去獲取那 10 條數(shù)據(jù)的詳情返回給客戶端。分析:這個(gè)例子的執(zhí)行過(guò)程中,在 Query 階段會(huì)在每個(gè) shard 上均有巨大的查詢量,返回給 coordinating node 時(shí)需要執(zhí)行大量數(shù)據(jù)的排序操作,并且保存到優(yōu)先級(jí)隊(duì)列的數(shù)據(jù)量也很大,占用大量節(jié)點(diǎn)機(jī)器內(nèi)存資源。
2.4 實(shí)現(xiàn)示例
private SearchHits getSearchHits(BoolQueryBuilder queryParam, int from, int size, String orderField) {
SearchRequestBuilder searchRequestBuilder = this.prepareSearch();
searchRequestBuilder.setQuery(queryParam).setFrom(from).setSize(size).setExplain(false);
if (StringUtils.isNotBlank(orderField)) {
searchRequestBuilder.addSort(orderField, SortOrder.DESC);
}
log.info("getSearchHits searchBuilder:{}", searchRequestBuilder.toString());
SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
log.info("getSearchHits searchResponse:{}", searchResponse.toString());
return searchResponse.getHits();
}2.5 小結(jié)
其實(shí) ES 對(duì)結(jié)果窗口的返回?cái)?shù)據(jù)有默認(rèn) 10000 條的限制(參數(shù):index.max_result_window = 10000),當(dāng) from + size 的條數(shù)大于 10000 條時(shí) ES 提示可以通過(guò) scroll 方式進(jìn)行分頁(yè),非常不建議調(diào)大結(jié)果窗口參數(shù)值。
3 Scroll 分頁(yè)方式
scroll 分頁(yè)方式類似關(guān)系型數(shù)據(jù)庫(kù)中的 cursor(游標(biāo)),首次查詢時(shí)會(huì)生成并緩存快照,返回給客戶端快照讀取的位置參數(shù)(scroll_id),后續(xù)每次請(qǐng)求都會(huì)通過(guò) scroll_id 訪問(wèn)快照實(shí)現(xiàn)快速查詢需要的數(shù)據(jù),有效降低查詢和存儲(chǔ)的性能損耗。
3.1 執(zhí)行過(guò)程
scroll 分頁(yè)方式在 Query 階段同樣也是 coordinating node 廣播查詢請(qǐng)求,獲取、合并、排序其他 shard 返回的數(shù)據(jù)_id 集合,不同的是 scroll 分頁(yè)方式會(huì)將返回?cái)?shù)據(jù)_id 的集合生成快照保存到 coordinating node 上。Fetch 階段以游標(biāo)的方式從生成的快照中獲取 size 條數(shù)據(jù)的_id,并去其他 shard 獲取數(shù)據(jù)詳情返回給客戶端,同時(shí)將下一次游標(biāo)開始的位置標(biāo)識(shí)_scroll_id 也返回。這樣下次客戶端發(fā)送獲取下一頁(yè)請(qǐng)求時(shí)帶上 scroll_id 標(biāo)識(shí),coordinating node 會(huì)從 scroll_id 標(biāo)記的位置獲取接下來(lái) size 條數(shù)據(jù),同時(shí)再次返回新的游標(biāo)位置標(biāo)識(shí) scroll_id,這樣依次類推直到取完所有數(shù)據(jù)。
以上就是ElasticSearch 深度分頁(yè)示例解析的詳細(xì)內(nèi)容,更多關(guān)于ElasticSearch 深度分頁(yè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringBoot應(yīng)用的打包和發(fā)布實(shí)現(xiàn)
本文主要介紹了SpringBoot應(yīng)用的打包和發(fā)布實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04
springboot Interceptor攔截器excludePathPatterns忽略失效
這篇文章主要介紹了springboot Interceptor攔截器excludePathPatterns忽略失效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Java嵌套for循環(huán)的幾種常見優(yōu)化方案
這篇文章主要給大家介紹了關(guān)于Java嵌套for循環(huán)的幾種常見優(yōu)化,在Java中優(yōu)化嵌套for循環(huán)可以通過(guò)以下幾種方式來(lái)提高性能和效率,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07
一文了解MyBatis Plus批量數(shù)據(jù)插入功能
mybatisPlus底層的新增方法是一條一條的新增的,下面這篇文章主要給大家介紹了MyBatis Plus批量數(shù)據(jù)插入功能的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-09-09
深入解析Java中的Classloader的運(yùn)行機(jī)制
這篇文章主要介紹了Java中的Classloader的運(yùn)行機(jī)制,包括從JVM方面講解類加載器的委托機(jī)制等,需要的朋友可以參考下2015-11-11
SpringBoot+Redis實(shí)現(xiàn)數(shù)據(jù)字典的方法
這篇文章主要介紹了SpringBoot+Redis實(shí)現(xiàn)數(shù)據(jù)字典的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
SpringCloud?集成Sentinel的實(shí)戰(zhàn)教程
這篇文章主要介紹了SpringCloud?集成Sentinel的詳細(xì)過(guò)程,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-08-08
spring boot 自動(dòng)更新靜態(tài)文件和后臺(tái)代碼的實(shí)例
下面小編就為大家分享一篇spring boot 自動(dòng)更新靜態(tài)文件和后臺(tái)代碼的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
SpringBoot Web詳解靜態(tài)資源規(guī)則與定制化處理
這篇文章主要介紹了SpringBoot web場(chǎng)景的靜態(tài)資源規(guī)則與定制化,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-06-06

