Elasticsearch聚合后分頁深入詳解


Elasticsearch聚合后分頁深入詳解

1、Elasticsearch支持聚合后分頁嗎,為什么?

不支持,看看Elasticsearch員工如何解讀。

這個問題,2014年在github上有很長的討論。究其為什么ES不支持聚合后分頁?可概括如下: 1)性能角度——聚合分頁會在大量的記錄中產生性能問題。 2)正確性角度——聚合的文檔計數不准確。 所以奇怪的事情可能會發生,如第二頁的第一項具有比第一頁的最后一個元素更高的計數。

具體為什么會不正確? 這是因為每個分片都提供了自己對有序列表應該是什么的看法,並將這些列表結合起來給出最終的結果值。 舉例如下: 對於如下的聚合:聚合出產品數據量的前5名。

GET /_search
{ "aggs" : { "products" : { "terms" : { "field" : "product", "size" : 5 } } } }

步驟1: 三個分片的統計計數如下:

步驟2:各分片取前5名。

步驟3:依據各分片前5名,聚合得出總前5名。

僅以產品C的排名作為舉例,產品C(50個)的數據來自分片A(6個)和分片C(44個)之和。 所以,排名第三。 實際產品C在分片B中還存在4個,只不過這四個按照排名處於第10位,取前5的時候,顯然取不到。 所以,導致聚合結果不准確。 官網有詳細舉例解讀。

2、Elasticsearch要實現聚合后分頁,該怎么辦?

方案:需要展示滿足條件的全部數據條數,即需要全量聚合,且按照某規則排序。 記住,如果數據基數大(十萬、百萬甚至千萬級),這必然會很慢。

步驟1:全量聚合,size設置為: 2147483647。

ES5.X/6.X版本設置為2147483647 , 它等於2^31-1, 是32位操作系統中最大的符號型整型常量; ES1.X 2.X版本設置為0。

步驟2:將聚合結果存入內存中,可以考慮list或map存儲。 這里存入list的_id是基於某種規則排序過的,如:基於插入時間。

步驟3:內存內分頁,基於list中存儲值結合偏移值進行篩選。 如每頁10條數據,取第一頁就是:取list中第0到第9個元素,以此類推。

步驟4:基於篩選出的值進行二次查詢獲取詳情。 此處的篩選條件已經能唯一確定一篇document。

3、“聚合后不能分頁,但能分區來取”,是什么鬼?

貌似,沒有起到分頁的作用。此處沒有深入研究。

4、聚合后分頁實戰

步驟1:建立索引

PUT book_index
{
  "mappings": { "book_type": { "properties": { "_key": { "type": "keyword", "ignore_above": 256 }, "pt": { "type": "date" }, "url": { "type": "keyword", "ignore_above": 256 }, "title": { "type": "text", "term_vector": "with_positions_offsets", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } }, "analyzer": "ik_smart" }, "abstr": { "type": "text", "term_vector": "with_positions_offsets", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } }, "analyzer": "ik_smart" }, "rplyinfo": { "type": "text", "term_vector": "with_positions_offsets", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } }, "analyzer": "ik_smart" }, "author": { "type": "keyword", "ignore_above": 256 }, "booktype": { "type": "keyword", "ignore_above": 256 }, "price": { "type": "long" } } } } }

步驟2:導入數據

舉例原因,假設后來導入百萬甚至千萬級別數據。

POST book_index/book_type/1 { "title":"《Elasticsearch深入理解》", "author":"ERicif", "abstr":"Elasticsearch實戰書籍", "relyinfo":"不錯,值得推薦", "booktype":"技術", "price":79, "pt":1543611840000 } POST book_index/book_type/2 { "title":"《大數據之路》", "author":"阿里巴巴", "abstr":"大數據實現", "relyinfo":"不錯,值得推薦2", "booktype":"技術", "price":89, "pt":1543011840000 } POST book_index/book_type/3 { "title":"《人性的弱點》", "author":"卡耐基", "abstr":"直擊人性", "relyinfo":"不錯,值得推薦2", "booktype":"勵志", "price":59, "pt":1543101840000 } POST book_index/book_type/4 { "title":"《Flow案例精編》", "author":"ERicif", "abstr":"Flow案例", "relyinfo":"還可以", "booktype":"技術", "price":57, "pt":1543201840000 } POST book_index/book_type/5 { "title":"《kibana案例精編》", "author":"ERicif", "abstr":"kibana干貨", "relyinfo":"還可以,不孬", "booktype":"技術", "price":53, "pt":1480539840000 }

步驟3:聚合

要求:按照以下條件聚合 1)相同作者出書量;(聚合) 2)相同作者的書,取時間最大的返回。(聚合后排序)

POST book_index/_search { "sort": [ { "pt": "desc" } ], "aggs": { "count_over_sim": { "terms": { "field": "author", "size": 2147483647, "order": { "pt_order": "desc" } }, "aggs": { "pt_order": { "max": { "field": "pt" } } } } }, "query": { "bool": { "must": [ { "bool": { "should": [ { "match": { "booktype": "技術" } } ] } }, { "range": { "pt": { "gte": 1451595840000, "lte": 1603201840000 } } } ] } }, "_source": { "includes": [ "title", "abstr", "pt", "booktype", "author" ] }, "from": 0, "size": 10, "highlight": { "pre_tags": [ "<span style=\"color:red\">" ], "post_tags": [ "</span>" ], "fields": { "title": {} } } }

步驟4:獲取關鍵信息存入list。

步驟5:二次遍歷+偏移截取分頁實現。

5、Elasticsearch聚合+分頁速度慢,該如何優化?

優化方案:改為廣度搜索方式。

“collect_mode” : “breadth_first”,

[ES官網]如果數據量越大,那么默認的使用深度優先的聚合模式生成的總分組數就會非常多,但是預估二級的聚合字段分組后的數據量相比總的分組數會小很多所以這種情況下使用廣度優先的模式能大大節省內存,從而通過優化聚合模式來大大提高了在某些特定場景下聚合查詢的成功率。

6、小結

待聚合的大小size取值越大,結果就越精確,而且計算最終結果的代價也越高; 耗時主要體現在: 第一:分片級別巨大的優先級隊列的管理成本; 第二:集群節點和客戶端之間的數據傳輸成本。

參考:

[1]Github解讀:http://t.cn/RQpTzSH [2]廣度優先遍歷:http://t.cn/RHndSgY [3]分區聚合:http://t.cn/RQpTbdO

 

 

原文鏈接: 

https://cloud.tencent.com/developer/article/1066373


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM