0、引言Elasticsearch社區(qū)中經(jīng)常看到慢查詢問題:“你能幫我看看Elasticsearch的響應(yīng)時間嗎?”或者是:“我的ES查詢耗時很長,我該怎么做?” 包含但不限于:Nested慢查詢、集群查詢慢、range查詢慢等問題。 1、兩個維度每當(dāng)我們得到這些類型的問題時,我們首先要深入研究兩個主要方面:
我們將首先關(guān)注開發(fā)方面的問題。 我們將獲得慢查詢,討論DSL查詢語言,并查看有助于改進(jìn)Elasticsearch查詢的小型常規(guī)選項。 2、開發(fā)維度—你的查詢有多慢?第一步是查看發(fā)送到群集的查詢所花費的時間。 在研究如何打開慢速日志時,Elasticsearch文檔可能有點不清楚,因此我將在下面展示一些示例。
向_cluster API發(fā)送放置請求以定義要打開的慢速日志級別:警告,信息,調(diào)試和跟蹤。 (有關(guān)日志記錄級別的更多信息參考:http:///E7Hqc5e。) 1curl -XPUT http://localhost:$ES_PORT/_cluster/settings -H 'Content-Type: application/json’ -d’
1curl -XPUT http://localhost:$ES_PORT/*/_settings?pretty -H 'Content-Type: application/json' -d
如您所見,搜索慢速日志再次根據(jù)搜索階段分解為單獨的日志文件:獲取(fetch)和查詢(query)。 1[2018-05-21T12:35:53,352][DEBUG ][index.search.slowlog.query] 在這里,您看到: 1 日期 一旦我們獲得了我們認(rèn)為花費的時間太長的查詢,我們就可以使用一些工具來分解查詢: 工具1:Profile APIProfile 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階段
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查詢的唯一方法。
filter原理推薦閱讀:吃透 | Elasticsearch filter和query的不同 5、開發(fā)維度——其他優(yōu)化5.1 避免使用script查詢避免使用腳本查詢來計算匹配。 推薦:建立索引時存儲計算字段。
5.2 避免使用wildcard查詢主要原因: 出現(xiàn)錯誤: 根本原因: 可能的優(yōu)化方案:
詳盡原理參考: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)。
6、配置維度——核心配置6.1 節(jié)點職責(zé)明晰區(qū)分路由節(jié)點、數(shù)據(jù)節(jié)點、候選主節(jié)點。路由節(jié)點的主要優(yōu)點是:
盡量將主節(jié)點與數(shù)據(jù)節(jié)點分開,因為它將減少所有群集的負(fù)載。以下時間開始考慮專用主節(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ā)一些問題。
騰訊基礎(chǔ)架構(gòu)部數(shù)據(jù)庫團(tuán)隊的推薦方案是:
建議參考: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)化查詢:
Elasticsearch優(yōu)化非一朝一夕之功,需要反復(fù)研究、實踐甚至閱讀源碼分析。
|
|