Elasticsearch 高基數(shù)聚合性能提升3倍,改動(dòng)了什么?
1、上問(wèn)題
這是來(lái)自球友實(shí)戰(zhàn)問(wèn)題。
大致需求介紹如下:
約 3600 萬(wàn)的數(shù)據(jù),其中關(guān)鍵字段如下所示:
| _id | creator |
|---|---|
| doc_1 | [張三,李四,王五,趙六] |
| doc_2 | [陳勝,吳廣,張三] |
用 cardinality 聚合統(tǒng)計(jì),creator 的個(gè)數(shù)有約 1300 萬(wàn)。
問(wèn)題:但在高基數(shù)(high cardinality)的情形下,性能不理想。
2、概念解讀:什么是高基數(shù)?
為了更精確解讀,這里直接拿:Elastic 官方博客只字不差的翻譯。
The?performance?of?terms?aggregations?can?be?greatly?impacted?by?the?cardinality?of?the?field?that?is?being?aggregated.?
Cardinality?refers?to?the?uniqueness?of?values?stored?in?a?particular?field.?
High?cardinality?means?that?a?field?contains?a?large?percentage?of?unique?values.?
Low?cardinality?means?that?a?field?contains?a?lot?of?repeated?values.?
For?example,?a?field?storing?country?names?will?be?relatively?low?cardinality?since?there?are?less?than?two?hundred?countries?in?the?world.?Alternatively,?a?field?storing?IBAN?numbers?or?email?addresses?is?high?cardinality?since?there?may?be?millions?of?unique?values?stored.
terms 聚合的性能可能會(huì)受到所聚合字段的基數(shù)的極大影響。
基數(shù)(Cardinality)是指存儲(chǔ)在特定字段中的值的唯一性。
高基數(shù):意味著一個(gè)字段包含很大比例的唯一值。
舉例:電子郵件地址可能會(huì)有數(shù)千萬(wàn)+唯一值,屬于高基數(shù)。(換了舉例)
低基數(shù):意味著一個(gè)字段包含很多重復(fù)的值。
舉例:因?yàn)槭澜缟仙儆?00個(gè)國(guó)家,國(guó)家名稱就是低基數(shù)。
3、問(wèn)題本質(zhì)
經(jīng)反復(fù)討論,本質(zhì)問(wèn)題:高基數(shù)業(yè)務(wù)場(chǎng)景下,聚合慢,達(dá)不到預(yù)期。
我記得剛?cè)肼殘?chǎng),我向?qū)煹膶?dǎo)師(輩分應(yīng)該是:師爺)當(dāng)面請(qǐng)教一個(gè)問(wèn)題,我說(shuō)了很長(zhǎng),他實(shí)在聽不下去了,就說(shuō)了一句:“你的問(wèn)題是什么?”,一語(yǔ)驚醒夢(mèng)中人,我一直記到今天。
后面當(dāng)我再向別人請(qǐng)教問(wèn)題的時(shí)候,我都提前打好草稿、列好提綱,快速且直接說(shuō)出重點(diǎn)、交流效率提升不少。
毫不夸張的說(shuō),能用簡(jiǎn)短的話描述清楚問(wèn)題,問(wèn)題就能基本解決了一大半。
4、怎么改進(jìn)呢?
經(jīng)反復(fù)討論,結(jié)合球友之前的實(shí)踐,思路如下:
第一 :對(duì)于字段值,存儲(chǔ)Hash值(寫入時(shí)處理)。
第二 :基于Hash 做聚合和統(tǒng)計(jì)分析操作。
5、Elasticsearch 有 Hash 值類型嗎?
早期版本(7.X 之前)沒有,但是 7.X 之后有。
如下借助 mapper-murmur3 插件實(shí)現(xiàn):
插件地址:
https://www.elastic.co/guide/en/elasticsearch/plugins/7.2/mapper-murmur3.html
murmur3 需要著重介紹一下:
維基百科解讀:MurmurHash 是一種非加密型哈希函數(shù),適用于一般的哈希檢索操作。
由 Austin Appleby 在 2008年發(fā)明, 并出現(xiàn)了多個(gè)變種,都已經(jīng)發(fā)布到了公有領(lǐng)域(public domain)。
與其它流行的哈希函數(shù)相比,對(duì)于規(guī)律性較強(qiáng)的 key,MurmurHash的隨機(jī)分布特征表現(xiàn)更良好。
Redis 在實(shí)現(xiàn)字典時(shí)用到了兩種不同的哈希算法,MurmurHash 便是其中一種(另一種是djb),在 Redis 中應(yīng)用十分廣泛,包括數(shù)據(jù)庫(kù)、集群、哈希鍵、阻塞操作等功能都用到了這個(gè)算法。
發(fā)明算法的作者被邀到 google 工作,該算法最新版本是 MurmurHash3 , 基于MurmurHash2改進(jìn)了一些小瑕疵,使得速度更快,實(shí)現(xiàn)了 32 位(低延時(shí))、128 位 HashKey,尤其對(duì)大塊的數(shù)據(jù),具有較高的平衡性與低碰撞率。
6、mapper-murmur3 插件實(shí)踐一把
第一步:插件安裝
bin/elasticsearch-plugin?install?mapper-murmur3
第二步:導(dǎo)入Demo測(cè)試
PUT?my_index
{
??"mappings":?{
????"properties":?{
??????"my_field":?{
????????"type":?"keyword",
????????"fields":?{
??????????"hash":?{
????????????"type":?"murmur3"
??????????}
????????}
??????}
????}
??}
}
PUT?my_index/_doc/1
{
??"my_field":?"This?is?a?document"
}
PUT?my_index/_doc/2
{
??"my_field":?"This?is?a?document"
}
GET?my_index/_search
{
??"aggs":?{
????"my_field_cardinality":?{
??????"terms":?{
????????"field":?"my_field.hash"?
??????},
?????"aggs":?{
????????"top_sales_hits":?{
??????????"top_hits":?{
????????????"size":?2
??????????}
????????}
??????}
????}
??}
}
聚合結(jié)果如下:

這時(shí)候,就能比較清晰的看出murmur3的作用:
屬于 Mapping的特定字段類型。 可以和keyword類型組合當(dāng)做復(fù)合類型使用。 _source ?不存儲(chǔ)結(jié)果值。 只在聚合后才能看到結(jié)果。
7、加了 mapper-murmur3 Hash 后效果如何呢?
球友實(shí)踐反饋如下:

8、在相對(duì)低基數(shù)聚合性能如何呢?
實(shí)戰(zhàn)一把。

8.1 模擬生成 1000W+數(shù)據(jù)。
文本文件輸入了 39415 name信息(隨機(jī)生成)。通過(guò) python-dsl 隨機(jī)生成寫入 ES集群。
寫入結(jié)果如下所示:

索引1:
PUT?my-index-000002
{
??"mappings":?{
????"properties":?{
??????"creator":{
????????"type":"keyword"
??????}
????}
??}
}
索引2:
PUT?my-index-000003
{
??"mappings":?{
????"properties":?{
??????"creator":?{
????????"type":?"keyword",
????????"fields":?{
??????????"hash":?{
????????????"type":?"murmur3"
??????????}
????????}
??????}
????}
??}
}
8.2 低基數(shù)有多低?
POST?my-index-000002/_search
{
??"size":?0,
??"aggs":?{
????"count_aggs":?{
??????"cardinality":?{
????????"field":?"creator"
??????}
????}
??}
}
去重后的結(jié)果:39415。 原始數(shù)據(jù)量:11509010。 占比:0.342%
雖然高、低基數(shù)沒有明確數(shù)據(jù)量多少的定義,但,這明顯是低基數(shù)。
8.2 聚合結(jié)果對(duì)比
POST?my-index-000002/_search
{
??"aggs":?{
????"terms_agg":?{
??????"terms":?{
????????"field":"creator",
????????"size":3,
????????"shard_size":1000
??????}
????}
??}
}

如上所示 ,未加Hash的索引聚合要被加了Hash 的快一倍!
這也初步說(shuō)明:Hash 在低基數(shù)聚合沒有效果。
9、小結(jié)
以上驗(yàn)證和測(cè)試僅供參考,實(shí)際選型需要結(jié)合業(yè)務(wù)場(chǎng)景實(shí)際,進(jìn)行充分驗(yàn)證后再做定奪。
類似高基數(shù)聚合業(yè)務(wù)場(chǎng)景,你實(shí)踐中的優(yōu)化點(diǎn)是什么?歡迎留言交流。
參考:
https://www.elastic.co/cn/blog/improving-the-performance-of-high-cardinality-terms-aggregations-in-elasticsearch
https://cloud.tencent.com/developer/article/1421924
加微信:elastic6(僅有少量坑位了),和 BAT 大佬一起精進(jìn) Elastic 技術(shù)!
推薦閱讀:
更短時(shí)間更快習(xí)得更多干貨!
