1. 程式人生 > >ES terms聚合統計效能優化實踐

ES terms聚合統計效能優化實踐

一、terms聚合統計,initialise 階段的耗時,有助於我們調整對應 aggs 的 execution_hint 引數選擇?

map:過濾之後,實際納入統計的doc數量特別少,但是欄位總的term數量超級多

適用場景:
過濾完之後,納入統計的doc很少
不適用場景:
過濾完之後,納入統計的doc很多

global_ordinals:過濾之後,實際納入統計的doc數量特別多,但是欄位總的term數量很少

適用場景:
過濾完之後,納入統計的doc很多,但是terms聚合欄位,總的token很少(即該欄位資料不離散)
不適用場景:
terms聚合欄位,總的token超級多

Terms aggregation預設的計算方式並非直觀感覺上的先查詢,然後在查詢結果上直接做聚合。

ES假定使用者需要聚合的資料集是海量的,如果將查詢結果全部讀取回來放到記憶體裡計算,記憶體消耗會非常大。因此ES利用了一種叫做global ordinals的資料結構來對聚合的欄位來做bucket分配,這個ordinals用有序的數值來代表欄位裡唯一的一個字串,因此為每個ordinals值分配一個bucket就等同於為每個唯一的token分配了bucket。 之後遍歷查詢結果的時候,可以將結果對映到各個bucket裡,就可以很快的統計出每個bucket裡的文件數了。
這種計算方式主要開銷在構建global ordinals和分配bucket上,如果索引包含的原始文件非常多,查詢結果包含的文件也很多,那麼預設的這種計算方式是記憶體消耗最小,速度最快的。
如果指定execution_hint:map則會更改聚合執行的方式,這種方式不需要構造global ordinals,而是直接將查詢結果拿回來在記憶體裡構造一個map來計算,因此在查詢結果集很小的情況下會顯著的比global ordinals快。
要注意的是這中間有一個平衡點,當結果集大到一定程度的時候,map的記憶體開銷帶來的代價可能就抵消了構造global ordinals的開銷,從而比global ordinals更慢,所以需要根據實際情況測試對比一下才能找好平衡點。

2、terms聚合統計,collect 階段的耗時,有助於我們調整對應 aggs 的 collect_mode 引數選擇。目前 Elasticsearch 支援 breadth_first 和 depth_first 兩種方式

terms 桶基於我們的資料動態構建桶;它並不知道到底生成了多少桶。 大多數時候對單個欄位的聚合查詢還是非常快的, 但是當需要同時聚合多個欄位時,就可能會產生大量的分組,最終結果就是佔用 es 大量記憶體,從而導致 OOM 的情況發生。

depth_first:多層聚合時,總的桶數量是可以預測,少量的,但是納入統計doc數量非常多。

適用場景:
F1和F2欄位總的token不是很多,這樣過濾之後納入統計的doc總共需要建的桶是少量的
不適用場景:


F1和F2欄位的token很多(資料非常離散)

breadth_first:多層聚合時,總的桶的數量特別多,但是最終納入第一層統計的doc數量是非常少的。

適用場景:
F1和F2欄位總的term不是很多,但是納入前n(由size引數確定)個桶統計doc很少
不適用場景:
納入前n個桶統計的doc很多