Elasticsearch慢查詢故障診斷

最近在作ES搜索調優,看了一些lucene搜索的文檔和代碼,本文用於總結調優過程當中學到的知識和本身的思考。node

在抓到ES慢查詢以後,會經過profile或者kibana的Search Profiler console查看具體慢在了哪裏。通常在執行profile search以前,須要稍微改變query語句裏的查詢內容,防止cache影響測試效果。算法

profile主要包括shard級別的query耗時、query語句rewrite耗時以及最終lucene collector的耗時。elasticsearch

通常主要關注query的耗時,profile返回的query部分詳細的展現了被rewrite後的查詢語句以及每一個子查詢的耗時。包括子查詢的類型(type),子查詢語句(description),子查詢耗時(time_in_nanos)和一個breakdown集合包含了lucene segements search各階段的耗時。從這個breakdown集合中能比較清晰的看到耗時的緣由,固然,前提是要理解breakdown裏每一個指標表明什麼意思和內部的實現邏輯。測試

breakdown裏的主要指標及lucene中的實現:ui

build_scorer:構造一個scorer的耗時。scorer主要用於對matching的doc進行打分和排序。build_scorer內部構造了迭代器,這個迭代器能夠遍歷全部matched document,構造迭代器是很是耗時的操做,由於涉及到對各子查詢的docId結果集構造倒排鏈或bitset,而且作conjunction生成最終可被迭代的docId bitset或倒排鏈。大多數查詢主要耗時在這一步。orm

next_doc: 尋找下一個匹配的document Id。這裏keyword, text等文本類型的字段會利用skipList,數值類型的數據會利用Tree結構快速找的下一個匹配的docoument Id。同時,這裏會記錄該doc命中的子查詢數量,用於最終的min_should_match之類的過濾。排序

advance: 相似於一個low level的next_doc。並非全部的query都能實現next_doc,好比must查詢走的advance去找下一個匹配的文檔。ip

score: 記錄socrer中對文檔打分的耗時,經過Freq,normal等數據結合tf-idf等算法計算出得分。資源

match: 記錄第二階段打分的耗時。有些查詢須要兩階段打分,好比短語查詢(phrase query) "chinese love china", 第一階段先找全部包含「chinese」、「love」、「china」三個term的文檔。第二階段再在第一階段匹配到到的全部文檔中計算「chinese」,"love","china"三個單詞的位置和順序是否知足條件,這一操做很是耗時,因此經過第一階段縮小匹配文檔的範圍。文檔

create_weight: 建立weight過程的耗時,weight就至關於lucene查詢的context,裏面包含了query,collector,indexreader等。

*_count: 記錄方法調用次數,好比next_doc_count:2,表明next_doc方法被調用了兩次。

除了query過程的詳細統計,還包括:

rewrite_time: query語句被重寫的耗時,lucene本身維護了一套查詢語句重寫邏輯,好比terms查詢中若是要查詢的terms個數小於16,會被重寫成多個TermQuery作or結合;若是大於16會被重寫成TermInSetQuery。

collector: query數據收集階段的各類指標。包括query用到的collector的個數,類型和耗時。ES默認使用的是SimpleTopScoreDocCollector。lucene的collector主要經過reduce方法對每一個segment上匹配的結果進行合併和排序,返回topN。

 

故障診斷過程當中,除了經過profile API定位慢查詢,也須要關注ES集羣的總體資源使用狀況,好比data node的CPU, Mem, 磁盤IO是否有瓶頸,單節點shard個數是否過多等。通常能夠經過cerebro或者elasticsearch_exporter+Prometheus來監控集羣狀態, 也能夠經過ES API查看相關指標。

相關文章
相關標籤/搜索