ES Terms 聚合數據不確定性


Elasticsearch是一個分布式的搜索引擎,每個索引都可以有多個分片,用來將一份大索引的數據切分成多個小的物理索引,解決單個索引數據量過大導致的性能問題,另外每個shard還可以配置多個副本,來保證高可靠以及更好的抗並發的能力。
將一個索引切分成多個shard,大多數時候是沒有問題的,但是在es里面如果索引被切分成多個shard,在使用group進行聚合時,可能會出現問題,參見官網文檔
先了解ES 聚合的核心概念:桶(bucket)和指標(metric)
  • 桶(bucket): 滿足特定條件的文檔的集合
  • 指標(metric): 對桶內的文檔進行聚合分析的操作

  聚合是由桶和指標組成的。聚合可能只有一個桶,可能只有一個指標,或者可能兩個都有。轉換成成對應的sql語句如下:

  select count(*) from Table_A  group by FieldA
其中:bucket 相當於 group by FieldA --> FieldA 字段內相同的數據,就會被划分到一個bucket中
   metric 相當於 count(*) --> 對每個FieldA  bucket中所有的數據計算一個數量
如下圖:
 
針對官網的例子,描述group count如果有多個shard可能會出現的問題
  • 有一份商品的索引數據,它有3個shard,每個shard的數據如下所示(括號內表示商品document count), 要獲取name字段中出現頻率最高的前5個
  • 客戶端向ES發送聚合請求,主節點接收到請求后,會向每個獨立的分片發送該請求。分片獨立的計算自己分片上的前5個name如下圖,然后返回:
  • 當所有的分片結果都返回后,在主節點進行結果的合並,再求出頻率最高的前5個,返回給客戶端, 結果如下圖:
  • 最后發現這個top5的結果,並不是100%精確的,只是一個近似精確的結果值:
  1. Product A在所有top5的shard數據里面都存在,所以它的結果是精確的
  2. Product C僅僅返回了 shard A 和 C里面的top5的數據,所以這里顯示50是不精確的, Product C在shard B里面也存在,但是它在 top5里面沒有出現,所以group后的結果實際上是有誤差的
  3. Product Z僅僅返回了2個shards的數據 因為第三個里面不存在,所以它的結果是准確的
  4. Product H實際上它的總數是44,橫跨三個shard 但是它在每個shard的top5里面並沒有出現,所以最終的top5里面也沒有這條數據

     這樣看來最終的top5的值並不是100% 准確的

雖然我們可以調大返回size的個數來提高精確度,但是size個數的提升,也意味着有更多的數據會被返回,從而會導致檢索性能的下降,這一點是需要找到平衡點的,  為解決這種不精確的統計,可以嘗試的方案:
  1. 聚合操作在單個shard時是精確的,也就是說我們索引的數據全部插入到一個shard的時候 它的聚合統計結果是准確的。
  2. 在索引數據的時候,使用route路由字段,將所有聚合的數據分布到同一個shard即可,這樣再聚合時也是精確的。 參見:ES Route
  • 第一種適合數據量不大的場景下,我們直接把數據放在一份索引里面,第二種辦法適合數據量比較大的場景下,我們通過業務字段將相同屬性的數據路由在同一個shard里面即可,具體使用哪個需要和具體的業務場景相結合。

    3. size與shard_size

  • size參數規定了最后返回的term個數(默認是10個)
  • shard_size參數規定了每個分片上返回的個數
  • 如果shard_size小於size,那么分片也會按照size指定的個數計算
  • 通過這兩個參數,如果我們想要返回前5個,size=5;shard_size可以設置大於5,這樣每個分片返回的詞條信息就會增多,相應的誤差幾率也會減小。

上面提到那個例子,如果聚合的key本來就很少,那么它的聚合結果也是准確的,比如按性別,月份聚合,因為這些返回的key,都是有限的,所以結果沒問題,但是一旦對分組的個數沒法確定,這種情況下出現問題的幾率就比較大,跨表或者跨分片聚合其實在任何db系統里面都會存在這種問題,所以我們應該盡量在設計業務時就考慮到這種特殊情況,然后最終做特殊處理。

 


免責聲明!

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



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