一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

為什么Elasticsearch查詢變得這么慢了?

 銘毅天下 2021-12-24

0、引言

Elasticsearch社區(qū)中經(jīng)常看到慢查詢問題:“你能幫我看看Elasticsearch的響應(yīng)時間嗎?”或者是:“我的ES查詢耗時很長,我該怎么做?”

包含但不限于:Nested慢查詢、集群查詢慢、range查詢慢等問題。

1、兩個維度

每當(dāng)我們得到這些類型的問題時,我們首先要深入研究兩個主要方面:

  • 配置維度 - 查看當(dāng)前系統(tǒng)資源和默認(rèn)Elasticsearch選項。

  • 開發(fā)維度 - 查看查詢,其結(jié)構(gòu)以及要搜索的數(shù)據(jù)的映射(Mapping)。

我們將首先關(guān)注開發(fā)方面的問題。 我們將獲得慢查詢,討論DSL查詢語言,并查看有助于改進(jìn)Elasticsearch查詢的小型常規(guī)選項。

2、開發(fā)維度—你的查詢有多慢?

第一步是查看發(fā)送到群集的查詢所花費的時間。 在研究如何打開慢速日志時,Elasticsearch文檔可能有點不清楚,因此我將在下面展示一些示例。

  • 首先,Elasticsearch中有兩個版本的慢速日志:索引慢速日志(index slow logs )和搜索慢速日志( search slow logs)。
    由于我們試圖解決的問題涉及慢查詢,我們將專注于搜索慢速日志。 但是,如果在索引文檔/添加文檔時問題解決了性能問題,那么我們將查看索引慢速日志。

默認(rèn)情況下,所有版本的Elasticsearch都會關(guān)閉慢速日志,因此您必須對群集設(shè)置和索引設(shè)置進(jìn)行一些更新。
這些示例適用于使用elasticsearch 6.2,但您可以在此處找到所有以前的版本。
只需將$ES_version替換為您正在使用的版本,
例如5.5版本設(shè)置官網(wǎng)參考:http:///E7Hq2NG。

向_cluster API發(fā)送放置請求以定義要打開的慢速日志級別:警告,信息,調(diào)試和跟蹤。 (有關(guān)日志記錄級別的更多信息參考:http:///E7Hqc5e。)

1curl -XPUT http://localhost:$ES_PORT/_cluster/settings -H 'Content-Type: application/json’ -d’
2{
3"transient" : {
4"logger.index.search.slowlog" : "DEBUG",
5"logger.index.indexing.slowlog" : "DEBUG"
6}
7}'
8

  • 所有慢速日志記錄都在索引級別啟用,因此您可以再次向index _settings API發(fā)送請求以打開,但如果您每月,每季度等都在滾動更新索引,則還必須添加到索引模板中。

  • 將API調(diào)用調(diào)整為索引設(shè)置以匹配您想要命中的慢日志時間閾值。 (您可以設(shè)置為0s以分析實例并收集正在發(fā)送的所有查詢,并設(shè)置為-1以關(guān)閉慢速日志。)
    使用您在_clustersettings中選擇使用的日志級別設(shè)置。 在這個例子中,“DEBUG”。
    ES_PORT是一個持久的環(huán)境變量。

1curl -XPUT http://localhost:$ES_PORT/*/_settings?pretty -H 'Content-Type: application/json' -d 
2 '{"index.search.slowlog.threshold.query.debug": "-1",
3   "index.search.slowlog.threshold.fetch.debug": "-1",}'

  • 現(xiàn)在,您需要收集日志。 每個分片生成慢速日志并按數(shù)據(jù)節(jié)點收集。 如果您只有一個包含五個主分片的數(shù)據(jù)節(jié)點(這是默認(rèn)值),您將在慢速日志中看到一個查詢的五個條目。 由于Elasticsearch中的搜索發(fā)生在每個分片中,因此每個分片都會看到一個。 每個數(shù)據(jù)節(jié)點存儲慢速日志,默認(rèn)情況如下

    /var/log/elasticsearch/$ClusterID_index_slowlog_query 

    /var/log/elasticsearch/$ClusterID_index_slowlog_fetch.

如您所見,搜索慢速日志再次根據(jù)搜索階段分解為單獨的日志文件:獲取(fetch)和查詢(query)。
現(xiàn)在我們在日志中有結(jié)果,我們可以拉入一個條目并將其分開。

1[2018-05-21T12:35:53,352][DEBUG ][index.search.slowlog.query
2[DwOfjJF] [blogpost-slowlogs][4] took[1s], took_millis[0], types[], 
3stats[], search_type[QUERY_THEN_FETCH], total_shards[5], 
4source[{"query":{"match":{"name":{"query":"hello world",
5 "operator":"OR","prefix_length":0,"max_expansions":50,
6"fuzzy_transpositions" :true,"lenient":false,"zero_terms_query":
7 "NONE","boost":1.0}}},"sort":[{"price": {"order":"desc"}}]}], 

在這里,您看到:

1 日期
2 時間戳 
3 日志級別 
4 慢速類型 
5 節(jié)點名稱 
6 索引名稱 
7 分片號 
8 時間花費 
9 查詢的主體(_source>)

一旦我們獲得了我們認(rèn)為花費的時間太長的查詢,我們就可以使用一些工具來分解查詢:

工具1:Profile API

Profile API提供有關(guān)搜索的信息頁面,并分解每個分片中發(fā)生的情況,直至每個搜索組件(match/range/match_phrase等)的各個時間。 搜索越詳細(xì),_profile輸出越詳細(xì)。

工具2:Kibana profiling 工具

這與_profileAPI密切相關(guān)。 它提供了各個搜索組件的完美的可視化效果表征各個分解階段以及各階段查詢的時間消耗。 同樣,這允許您輕松選擇查詢的問題區(qū)域。


3、開發(fā)維度—Elasticsearch的查詢原理

現(xiàn)在我們已經(jīng)確定了一個很慢的查詢,我們通過一個分析器profile來運行它。 但是,查看單個組件時間結(jié)果并未使搜索速度更快。 怎么辦?

通過兩個階段(下面)了解查詢的工作原理,允許您以從速度和相關(guān)性方面獲得Elasticsearch最佳結(jié)果的方式重新設(shè)計查詢。

3.1 Query階段

  • 路由節(jié)點接受該查詢。

  • 路由節(jié)點識別正在搜索的索引(或多個索引)。

  • 路由節(jié)點生成一個節(jié)點列表,其中包含索引的分片(主要和副本的混合)。

  • 路由節(jié)點將查詢發(fā)送到節(jié)點(上一步節(jié)點列表列出的節(jié)點)。

  • 節(jié)點上的分片處理查詢。

  • 查詢(默認(rèn)情況下)對前10個文檔進(jìn)行評分。

  • 該列表將發(fā)送回路由節(jié)點。

3.2 fetch階段

獲取階段由路由節(jié)點開始,路由節(jié)點確定每個分片發(fā)送的50個(5個分片×10個結(jié)果)結(jié)果中的前10個文檔。

路由節(jié)點向分片發(fā)出對前10個文檔的請求。 (可能是包含最高得分文檔的一個分片,或者它們可能分散在多個分片中。)

返回列表后,主節(jié)點會在查詢響應(yīng)的_hits部分中顯示文檔。

4、開發(fā)維度—filter過濾器查詢優(yōu)化

結(jié)果分?jǐn)?shù)是Elasticsearch的關(guān)鍵。 通常,當(dāng)您使用搜索引擎時,您需要最準(zhǔn)確的結(jié)果。 例如,如果您正在搜索“蘋果”,您不希望結(jié)果包括“蘋果手機(jī)”。

Elasticsearch根據(jù)您提供的參數(shù)對查詢結(jié)果進(jìn)行評分。

雖然查詢相關(guān)性不是本篇文章的重點,但重要的是在此提及,因為如果您有快速搜索需求但結(jié)果不是您要查找的結(jié)果,則整個搜索都是浪費時間。
那么,
你如何加快搜索速度?

4.1 查詢時,使用query-bool-filter組合取代普通query

提高搜索性能的一種方法是使用過濾器。 過濾后的查詢可能是您最需要的。

首先過濾是很重要的,因為搜索中的過濾器不會影響文檔分?jǐn)?shù)的結(jié)果,因此您在資源方面使用很少的資源來將搜索結(jié)果范圍縮小到很小。

使用過濾查詢,結(jié)合使用布爾匹配,您可以在評分之前搜索包含X的所有文檔,或者不包含Y的所有文檔。此外,可以filter是可以被緩存的。

過濾器filter查詢不是加速Elasticsearch查詢的唯一方法。

【from騰訊】默認(rèn)情況下,ES通過一定的算法計算返回的每條數(shù)據(jù)與查詢語句的相關(guān)度,并通過score字段來表征。

但對于非全文索引的使用場景,用戶并不care查詢結(jié)果與查詢條件的相關(guān)度,只是想精確的查找目標(biāo)數(shù)據(jù)。

此時,可以通過query-bool-filter組合來讓ES不計算score,
并且盡可能的緩存filter的結(jié)果集,供后續(xù)包含相同filter的查詢使用,提高查詢效率。

filter原理推薦閱讀:吃透 | Elasticsearch filter和query的不同

5、開發(fā)維度——其他優(yōu)化

5.1 避免使用script查詢

避免使用腳本查詢來計算匹配。 推薦:建立索引時存儲計算字段。

例如,我們有一個包含大量用戶信息的索引,我們需要查詢編號以“1234”開頭的所有用戶。 

您可能希望運行類似“source”的腳本查詢:

doc ['num'].value.startsWith('1234')

此查詢非常耗費資源并且會降低整個系統(tǒng)的速度。  合理的建議:考慮在索引時添加名為“num_prefix”的字段。
然后我們可以查詢

“name_prefix”:“1234”。

5.2 避免使用wildcard查詢

主要原因:
wildcard類似mysql中的like,和分詞完全沒有了關(guān)系。

出現(xiàn)錯誤:
用戶輸入的字符串長度沒有做限制,導(dǎo)致首尾通配符中間可能是很長的一個字符串。 后果就是對應(yīng)的wildcard Query執(zhí)行非常慢,
非常消耗CPU。

根本原因:
為了加速通配符和正則表達(dá)式的匹配速度,Lucene4.0開始會將輸入的字符串模式構(gòu)建成一個DFA (Deterministic Finite Automaton),帶有通配符的pattern構(gòu)造出來的DFA可能會很復(fù)雜,開銷很大。

可能的優(yōu)化方案:

  1. wildcard query應(yīng)杜絕使用通配符打頭,實在不得已要這么做,就一定需要限制用戶輸入的字符串長度。

  2. 最好換一種實現(xiàn)方式,通過在index time做文章,選用合適的分詞器,比如nGram tokenizer預(yù)處理數(shù)據(jù),然后使用更廉價的term query來實現(xiàn)同等的模糊搜索功能。

  3. 對于部分輸入即提示的應(yīng)用場景,可以考慮優(yōu)先使用completion suggester, phrase/term/suggeter一類性能更好,模糊程度略差的方式查詢,待suggester沒有匹配結(jié)果的時候,再fall back到更模糊但性能較差的wildcard, regex, fuzzy一類的查詢。

詳盡原理參考:https:///article/171

5.3 合理使用keyword類型

ES5.x里對數(shù)值型字段做TermQuery可能會很慢。

在ES5.x+里,一定要注意數(shù)值類型是否需要做范圍查詢,看似數(shù)值,但其實只用于Term或者Terms這類精確匹配的,應(yīng)該定義為keyword類型。

典型的例子就是索引web日志時常見的HTTP Status code。

詳盡原理參考:https:///article/446

5.4 控制字段的返回

一是:數(shù)據(jù)建模規(guī)劃的時候,在Mapping節(jié)點對于僅存儲、是否構(gòu)建倒排索引通過enabled、index參數(shù)進(jìn)行優(yōu)化。

二是:_source控制返回,不必要的字段不需要返回,舉例:采集的原文章詳情內(nèi)容頁,根據(jù)需要決定是否返回。

5.5 讓Elasticsearch干它擅長的事情

在檢索/聚合結(jié)果后,業(yè)務(wù)系統(tǒng)還有沒有做其他復(fù)雜的操作,花費了多少時間?

這塊是最容易忽視的時間耗費擔(dān)當(dāng)。

Elasticsearch顯然更擅長檢索、全文檢索,其他不擅長的事情,盡量不要ES處理。比如:頻繁更新、確保數(shù)據(jù)的ACID特性等操作。

6、配置維度——核心配置

6.1 節(jié)點職責(zé)明晰

區(qū)分路由節(jié)點、數(shù)據(jù)節(jié)點、候選主節(jié)點。

路由節(jié)點的主要優(yōu)點是:

  1. 由于路由節(jié)點減少了搜索和聚合的壓力,因此數(shù)據(jù)節(jié)點上的內(nèi)存壓力略有降低;

  2. “智能路由”——因為他們知道所有數(shù)據(jù)存在的地方,他們可以避免額外的跳躍;“智能路由”——因為他們知道所有數(shù)據(jù)存在的地方,他們可以避免額外的跳躍;

  3. 從架構(gòu)上講,將路由節(jié)點用作集群的訪問點非常有用,因此您的應(yīng)用程序無需了解詳細(xì)信息。 從架構(gòu)上講,將路由節(jié)點用作集群的訪問點非常有用,因此您的應(yīng)用程序無需了解詳細(xì)信息。

盡量將主節(jié)點與數(shù)據(jù)節(jié)點分開,因為它將減少所有群集的負(fù)載。

以下時間開始考慮專用主節(jié)點:

  1. 群集大小開始變得難以駕馭,可能像10個節(jié)點或更高?

  2. 您會看到由于負(fù)載導(dǎo)致集群不穩(wěn)定(通常由內(nèi)存壓力引起,導(dǎo)致長GC,導(dǎo)致主節(jié)點暫時從集群中退出)您會看到由于負(fù)載導(dǎo)致集群不穩(wěn)定(通常由內(nèi)存壓力引起,導(dǎo)致長GC,導(dǎo)致主節(jié)點暫時從集群中退出)

分離主節(jié)點的主要目的是使“主節(jié)點的職責(zé)”與負(fù)載隔離,因為高負(fù)載可能導(dǎo)致長GC,從而導(dǎo)致集群不穩(wěn)定。

分離主節(jié)點后,一個高負(fù)載的集群只會影響數(shù)據(jù)節(jié)點(顯然仍然不好),但能保證主節(jié)點穩(wěn)定,一旦集群超載,基本上專門的主節(jié)點給你喘息的空間,而不是整個集群走向崩潰。

另外,與數(shù)據(jù)節(jié)點相比,主節(jié)點通??梢苑浅!拜p”。幾GB的RAM,中等CPU,普通磁盤等或許就能滿足需求(需要根據(jù)實際業(yè)務(wù)場景權(quán)衡)。

推薦閱讀:http:///E7HM4ML

6.2 分配合理的堆內(nèi)存

搜索引擎旨在快速提供答案。 為此,他們使用的大多數(shù)數(shù)據(jù)結(jié)構(gòu)必須駐留在內(nèi)存中。 在很大程度上,他們假設(shè)你為他們提供了足夠的記憶。 如果不是這種情況,這可能會導(dǎo)致問題 - 不僅僅是性能問題,還有集群的可靠性問題。

合理的堆內(nèi)存大小配置建議:宿主機(jī)內(nèi)存大小的一半和31GB,取最小值

推薦閱讀:干貨 | 吃透Elasticsearch 堆內(nèi)存

6.3 設(shè)置合理的分片數(shù)和副本數(shù)

shard數(shù)量設(shè)置過多或過低都會引發(fā)一些問題。

  1. shard數(shù)量過多,則批量寫入/查詢請求被分割為過多的子寫入/子查詢,導(dǎo)致該index的寫入、查詢拒絕率上升;

對于數(shù)據(jù)量較大的index,當(dāng)其shard數(shù)量過小時,無法充分利用節(jié)點資源,造成機(jī)器資源利用率不高 或 不均衡,影響寫入/查詢的效率。

對于每個index的shard數(shù)量,可以根據(jù)數(shù)據(jù)總量、寫入壓力、節(jié)點數(shù)量等綜合考量后設(shè)定,然后根據(jù)數(shù)據(jù)增長狀態(tài)定期檢測下shard數(shù)量是否合理。

騰訊基礎(chǔ)架構(gòu)部數(shù)據(jù)庫團(tuán)隊的推薦方案是:

  1. 對于數(shù)據(jù)量較小(100GB以下)的index,往往寫入壓力查詢壓力相對較低,一般設(shè)置3~5個shard,副本設(shè)置為1即可(也就是一主一從,共兩副本)

  2. 對于數(shù)據(jù)量較大(100GB以上)的index:一般把單個shard的數(shù)據(jù)量控制在(20GB~50GB)

讓index壓力分?jǐn)傊炼鄠€節(jié)點:可通過index.routing.allocation.totalshardsper_node參數(shù),強(qiáng)制限定一個節(jié)點上該index的shard數(shù)量,讓shard盡量分配到不同節(jié)點上

綜合考慮整個index的shard數(shù)量,如果shard數(shù)量(不包括副本)超過50個,就很可能引發(fā)拒絕率上升的問題,此時可考慮把該index拆分為多個獨立的index,分?jǐn)倲?shù)據(jù)量,同時配合routing使用,降低每個查詢需要訪問的shard數(shù)量。

建議參考:Elasticsearch究竟要設(shè)置多少分片數(shù)?

6.4 設(shè)置合理的線程池和隊列大小

節(jié)點包含多個線程池,以便改進(jìn)節(jié)點內(nèi)線程內(nèi)存消耗的管理方式。 其中許多池也有與之關(guān)聯(lián)的隊列,這允許保留掛起的請求而不是丟棄。

search線程——用于計數(shù)/搜索/推薦操作。 線程池類型為fixed_auto_queue_size,大小為int((available of available_ * 3)/ 2)+ 1,初始隊列大小為1000。

5.X版本之后,線程池設(shè)置是節(jié)點級設(shè)置。因此,無法通過群集設(shè)置API更新線程池設(shè)置。

查看線程池的方法

1GET /_cat/thread_pool

6.5 硬件資源的實時監(jiān)控

排查一下慢查詢時間點的時候,注意觀察服務(wù)器的CPU, load average消耗情況,是否有資源消耗高峰,可以借助:xpack、cerbero或者elastic-hd工具查看。

當(dāng)您遇到麻煩并且群集工作速度比平時慢并且使用大量CPU功率時,您知道需要做一些事情才能使其再次運行。 當(dāng)Hot Threads API可以為您提供查找問題根源的必要信息。 熱線程hot thread是一個Java線程,它使用高CPU量并執(zhí)行更長的時間。

Hot Threads API返回有關(guān)ElasticSearch代碼的哪一部分是最耗費cpu或ElasticSearch由于某種原因而被卡住的信息。

熱線程使用方法:

1GET /_nodes/hot_threads

7、小結(jié)

回答文章開頭的問題:——為什么Elasticsearch查詢變得這么慢了?

和大數(shù)據(jù)量的業(yè)務(wù)場景有關(guān),您可以通過幾個簡單的步驟優(yōu)化查詢:

  1. 啟用慢速日志記錄,以便識別長時間運行的查詢

  2. 通過_profiling API運行已識別的搜索,以查看各個子查詢組件的時間通過_profiling API運行已識別的搜索,以查看各個子查詢組件的時間

  3. 過濾,過濾,過濾過濾,過濾,過濾

Elasticsearch優(yōu)化非一朝一夕之功,需要反復(fù)研究、實踐甚至閱讀源碼分析。
本文綜合了國外、國內(nèi)很多優(yōu)秀的實踐建議,核心點都已經(jīng)實踐驗證可行。
歡迎大家留言討論!

參考:
http:///E7HJaPI
http:///RQSwH4X
http:///RInoI4c

加入星球,更短時間更快習(xí)得更多干貨!

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产不卡的视频在线观看| 国产一区欧美午夜福利| 老司机亚洲精品一区二区| 爱草草在线观看免费视频| 亚洲av在线视频一区| 99久久国产亚洲综合精品| 国产91色综合久久高清| 欧美一区二区口爆吞精| 成人精品视频在线观看不卡| 手机在线观看亚洲中文字幕| 午夜视频在线观看日韩| 午夜福利精品视频视频| 国产一区在线免费国产一区| 婷婷色网视频在线播放| 伊人色综合久久伊人婷婷| 日韩成人高清免费在线| 国产一级不卡视频在线观看| 亚洲中文字幕有码在线观看| 日本本亚洲三级在线播放| 日本精品理论在线观看| 亚洲天堂精品1024| 国产精品欧美日韩中文字幕| 国产又粗又黄又爽又硬的| 久久碰国产一区二区三区| 成人免费观看视频免费| 国产精品一区二区香蕉视频| 日本淫片一区二区三区| 精品日韩中文字幕视频在线| 国产肥女老熟女激情视频一区| 99精品国产一区二区青青| 亚洲午夜av一区二区| 日本熟妇熟女久久综合| 天海翼高清二区三区在线| 我要看日本黄色小视频| 国产在线小视频你懂的| 日韩在线欧美一区二区| 久久精品国产在热久久| 亚洲国产精品无遮挡羞羞| 欧美日韩人妻中文一区二区| av国产熟妇露脸在线观看| 国产主播精品福利午夜二区|