自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

兩小時 Elasticsearch 性能優(yōu)化,直接把慢查詢干團滅了……

運維 新聞
公共集群的機器負載分布不均衡的問題,業(yè)務的查詢和流量不可控等各種各樣的問題,要節(jié)省機器資源就一定會面對這種各種各樣的問題,除非土豪式做法,每個業(yè)務都擁有自己的機器資源,這里面有很多很多頗具技術(shù)挑戰(zhàn)的事情。

?問題:慢查詢

搜索平臺的公共集群,由于業(yè)務眾多,對業(yè)務的es查詢語法缺少約束,導致問題頻發(fā)。業(yè)務可能寫了一個巨大的查詢直接把集群打掛掉,但是我們平臺人力投入有限,也不可能一條條去審核業(yè)務的es查詢語法,只能通過后置的手段去保證整個集群的穩(wěn)定性,通過slowlog分析等,下圖中cpu已經(jīng)100%了。

圖片

?

昨天剛好手頭有一點點時間,就想著能不能針對這些情況,把影響最壞的業(yè)務抓出來,進行一些改善,于是昨天花了2小時分析了一下,找到了一些共性的問題,可以通過平臺來很好的改善這些情況。

首先通過slowlog抓到一些耗時比較長的查詢,例如下面這個索引的查詢耗時基本都在300ms以上:


{
"from": 0,
"size": 200,
"timeout": "60s",
"query": {
"bool": {
"must": \[
{
"match": {
"source": {
"query": "5",
"operator": "OR",
"prefix\_length": 0,
"fuzzy\_transpositions": true,
"lenient": false,
"zero\_terms\_query": "NONE",
"auto\_generate\_synonyms\_phrase\_query": "false",
"boost": 1
}
}
},
{
"terms": {
"type": \[
"21"
\],
"boost": 1
}
},
{
"match": {
"creator": {
"query": "0d754a8af3104e978c95eb955f6331be",
"operator": "OR",
"prefix\_length": 0,
"fuzzy\_transpositions": "true",
"lenient": false,
"zero\_terms\_query": "NONE",
"auto\_generate\_synonyms\_phrase\_query": "false",
"boost": 1
}
}
},
{
"terms": {
"status": \[
"0",
"3"
\],
"boost": 1
}
},
{
"match": {
"isDeleted": {
"query": "0",
"operator": "OR",
"prefix\_length": 0,
"fuzzy\_transpositions": "true",
"lenient": false,
"zero\_terms\_query": "NONE",
"auto\_generate\_synonyms\_phrase\_query": "false",
"boost": 1
}
}
}
\],
"adjust\_pure\_negative": true,
"boost": 1
}
},
"\_source": {
"includes": \[
\],
"excludes": \[\]
}
}

這個查詢比較簡單,翻譯一下就是:

SELECT guid FROM xxx WHERE source=5 AND type=21 AND creator='0d754a8af3104e978c95eb955f6331be' AND status in (0,3) AND isDeleted=0;

?慢查詢分析

這個查詢問題還挺多的,不過不是今天的重點。比如這里面不好的一點是還用了模糊查詢fuzzy_transpositions,也就是查詢ab的時候,ba也會被命中,其中的語法不是今天的重點,可以自行查詢,我估計這個是業(yè)務用了SDK自動生成的,里面很多都是默認值。

第一反應當然是用filter來代替match查詢,一來filter可以緩存,另外避免這種無意義的模糊匹配查詢,但是這個優(yōu)化是有限的,并不是今天講解的關(guān)鍵點,先忽略。

1、錯用的數(shù)據(jù)類型

我們通過kibana的profile來進行分析,耗時到底在什么地方?es有一點就是開源社區(qū)很活躍,文檔齊全,配套的工具也非常的方便和齊全。

圖片

可以看到大部分的時間都花在了PointRangQuery里面去了,這個是什么查詢呢?為什么這么耗時呢?這里就涉及到一個es的知識點,那就是對于integer這種數(shù)字類型的處理。在es2.x的時代,所有的數(shù)字都是按keyword處理的,每個數(shù)字都會建一個倒排索引,這樣查詢雖然快了,但是一旦做范圍查詢的時候。比如 type>1 and type<5就需要轉(zhuǎn)成 type in (1,2,3,4,5)來進行,大大的增加了范圍查詢的難度和耗時。

之后es做了一個優(yōu)化,在integer的時候設計了一種類似于b-tree的數(shù)據(jù)結(jié)構(gòu),加速范圍的查詢,詳細可以參考(https://elasticsearch.cn/article/446)

所以在這之后,所有的integer查詢都會被轉(zhuǎn)成范圍查詢,這就導致了上面看到的isDeleted的查詢的解釋。那么為什么范圍查詢在我們這個場景下,就這么慢呢?能不能優(yōu)化。

明明我們這個場景是不需要走范圍查詢的,因為如果走倒排索引查詢就是O(1)的時間復雜度,將大大提升查詢效率。由于業(yè)務在創(chuàng)建索引的時候,isDeleted這種字段建成了Integer類型,導致最后走了范圍查詢,那么只需要我們將isDeleted類型改成keyword走term查詢,就能用上倒排索引了。

實際上這里還涉及到了es的一個查詢優(yōu)化。類似于isDeleted這種字段,毫無區(qū)分度的倒排索引的時候,在查詢的時候,es是怎么優(yōu)化的呢?

2、多個Term查詢的順序問題

實際上,如果有多個term查詢并列的時候,他的執(zhí)行順序,既不是你查詢的時候,寫進去的順序。

圖片

?例如上面這個查詢,他既不是先執(zhí)行source=5再執(zhí)行type=21按照你代碼的順序執(zhí)行過濾,也不是同時并發(fā)執(zhí)行所有的過濾條件,然后再取交集。es很聰明,他會評估每個filter的條件的區(qū)分度,把高區(qū)分度的filter先執(zhí)行,以此可以加速后面的filter循環(huán)速度。比如creator=0d754a8af3104e978c95eb955f6331be查出來之后10條記錄,他就會優(yōu)先執(zhí)行這一條。

怎么做到的呢?其實也很簡單,term建的時候,每一個term在寫入的時候都會記錄一個詞頻,也就是這個term在全部文檔里出現(xiàn)的次數(shù),這樣我們就能判斷當前的這個term他的區(qū)分度高低了。

3、為什么PointRangeQuery在這個場景下非常慢

上面提到了這種查詢的數(shù)據(jù)結(jié)構(gòu)類似于b-tree,他在做范圍查詢的時候,非常有優(yōu)勢,Lucene將這顆B-tree的非葉子結(jié)點部分放在內(nèi)存里,而葉子結(jié)點緊緊相鄰存放在磁盤上。當作range查詢的時候,內(nèi)存里的B-tree可以幫助快速定位到滿足查詢條件的葉子結(jié)點塊在磁盤上的位置,之后對葉子結(jié)點塊的讀取幾乎都是順序的。

圖片

總結(jié)就是這種結(jié)構(gòu)適合范圍查詢,且磁盤的讀取是順序讀取的。但是在我們這種場景之下,term查詢可就麻煩了,數(shù)值型字段的TermQuery被轉(zhuǎn)換為了PointRangeQuery。這個Query利用Block k-d tree進行范圍查找速度非???,但是滿足查詢條件的docid集合在磁盤上并非向Postlings list那樣按照docid順序存放,也就無法實現(xiàn)postings list上借助跳表做蛙跳的操作。

要實現(xiàn)對docid集合的快速advance操作,只能將docid集合拿出來,做一些再處理。這個處理過程在org.apache.lucene.search.PointRangeQuery#createWeight這個方法里可以讀取到。這里就不貼冗長的代碼了,主要邏輯就是在創(chuàng)建scorer對象的時候,順帶先將滿足查詢條件的docid都選出來,然后構(gòu)造成一個代表docid集合的bitset,這個過程和構(gòu)造Query cache的過程非常類似。之后advance操作,就是在這個bitset上完成的。所有的耗時都在構(gòu)建bitset上,因此可以看到耗時主要在build_scorer上了。

驗證

找到原因之后,就可以開始驗證了。將原來的integer類型全部改成keyword類型,如果業(yè)務真的有用到范圍查詢,應該會報錯。通過搜索平臺的平臺直接修改配置,修改完成之后,重建索引就生效了。

圖片

索引切換之后的效果也非常的明顯,通過kibana的profile分析可以看到,之前需要接近100ms的PointRangQuery現(xiàn)在走倒排索引,只需要0.5ms的時間。

圖片

之前這個索引的平均latency在100ms+,這個是es分片處理的耗時,從搜索行為開始,到搜索行為結(jié)束的打點,不包含網(wǎng)絡傳輸時間和連接建立時間,單純的分片內(nèi)的函數(shù)的處理時間的平均值,正常情況在10ms左右。

圖片

經(jīng)過調(diào)整之后的耗時降到了10ms內(nèi)。

圖片

通過監(jiān)控查看慢查詢的數(shù)量,立即減少到了0。

圖片

未來

后續(xù)將通過搜索平臺側(cè)的能力來保證業(yè)務的查詢,所有的integer我們會默認你記錄的是狀態(tài)值,不需要進行范圍查詢,默認將會修改為keyword類型,如果業(yè)務確實需要范圍查詢,則可以通過后臺再修改回integer類型,這樣可以保證在業(yè)務不了解es機制的情況下,也能擁有較好的性能,節(jié)省機器計算資源。

目前還遇到了很多問題需要優(yōu)化。例如重建索引的時候,機器負載太高。公共集群的機器負載分布不均衡的問題,業(yè)務的查詢和流量不可控等各種各樣的問題,要節(jié)省機器資源就一定會面對這種各種各樣的問題,除非土豪式做法,每個業(yè)務都擁有自己的機器資源,這里面有很多很多頗具技術(shù)挑戰(zhàn)的事情。

實際上,在這一塊還是非常利于積累經(jīng)驗,對于es的了解和成長也非???,在查問題的過程中,對于搜索引擎的使用和了解會成長的非???。不僅如此,很多時候,我們用心地看到生產(chǎn)的問題,持續(xù)的跟蹤,一定會有所收獲。大家遇到生產(chǎn)問題的時候,務必不要放過任何細節(jié),這個就是你收獲的時候,比你寫100行的CRUD更有好處。

責任編輯:張燕妮 來源: 哈啰技術(shù)
相關(guān)推薦

2024-03-07 11:03:21

ElasticseaES索引

2009-03-24 09:12:15

2015-10-26 11:53:36

OpenStackOpenStack部署RDO

2023-01-26 11:43:03

線程池CPUJava

2023-10-11 08:36:42

復合查詢腳本查詢

2016-11-14 14:10:15

電信斷網(wǎng)寬帶網(wǎng)絡

2009-07-28 09:18:17

2017-11-01 16:15:23

SQL優(yōu)化權(quán)限類型案例

2020-05-12 20:40:58

SQL慢查詢優(yōu)化數(shù)據(jù)庫

2023-01-09 18:12:20

多線程故障組件

2011-10-25 15:49:57

VPN

2021-10-18 22:07:05

裝機顯卡硬件

2009-03-09 09:27:16

Facebook社交網(wǎng)站健康

2010-12-24 10:09:04

2014-12-19 16:08:18

2009-05-08 08:59:47

微軟Windows 7操作系統(tǒng)

2009-04-30 13:37:38

安全掛馬技術(shù)沙龍

2013-03-13 10:15:02

應用經(jīng)濟調(diào)查數(shù)據(jù)智能機

2024-11-11 14:57:56

JWTSession微服務

2022-04-22 14:41:12

美團慢查詢數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號