天天看點

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

作者:老李講安全

1、企業級實戰 DSL(資料已經脫敏)

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?
Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?
Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

2、大家可以看一下,能發現哪些問題?

根據我的實戰和咨詢經驗,我發現如下幾個問題。

當然,這是在和球友交流确認問題之後總結出來的。

2.1 問題1:bool 組合嵌套過深。

官方實際是有參數來限制的,indices.query.bool.max_nested_depth——bool 最大支援的嵌套層數是 20,并且過大的嵌套層數會導緻“堆棧溢出”異常問題。

那 bool 組合嵌套越深是不是越慢呢?

我拿 228 萬+的微網誌資料(JMeter 模拟100使用者并發)作為樣例索引資料進行驗證。

  • 實驗1:嵌套 10 層;執行 5 次,平均耗時:835 ms。
  • 實驗2:嵌套 2 層;執行 5 次,平均耗時:674.8 ms。

對比看實驗 2 執行查詢較實驗 1 的查詢要快!

其實,初步結論是嵌套越深,執行越慢!

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?
Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

2.2 問題2:大量使用 wildcard 查詢。

我之前血淋淋的教訓告訴大家,非必要不使用 wildcard !

尤其資料量大的場景。

參見:Elasticsearch 警惕使用 wildcard 檢索!然後呢?

依然拿 228 萬+的微網誌資料(JMeter 模拟 100 使用者并發)作為樣例索引資料進行驗證。

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

檢索語句如下:

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

使用:match_phrase 短語比對較使用 wildcard 模糊比對效率提升:6.34 倍!

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

初步結論:非必要,不使用 wildcard。

2.3 問題3:"track_total_hits": 2147483647 沒有必要搞這麼大?

認知前提:Elasticsearch 中 max_result_window 這個參數大家比較熟悉,就是允許 from + size 翻頁檢索命中的最多文檔數為:10000 條記錄。

那麼問題來了,如果命中資料量超過 10000萬怎麼辦?

  • 一方面:我們可以修改:max_result_window 的預設值,但預設值修改要慎之又慎。
  • 另一方面:我們可以在執行檢索的時候加上 track_total_hits 這個參數。
Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

問題來了?什麼場景需要單獨設定 track_total_hits 參數?什麼時候不需要呢?

  • 場景一:當索引設定層面設定了 index.sort 後,本質上寫入的資料已經進行了預排序。如果隻對前 N 個結果感興趣,而不關心總命中數,可以簡單地将 track_total_hits 設定為 false。
  • 場景二:針對 filter 過濾檢索的場景,使用者僅關注是否存在,不關注相關性。可以分為如下兩種情況:
Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

(1)情況2.1:将 track_total_hits 設定為 false,檢索結果将不再傳回 hits.total 的具體值。

(2)情況2.2:将 track_total_hits 設定為給定的 N, 那麼每個分片待召回 N 個文檔後就傳回。除此之外的業務場景,建議慎用 track_total_hits:true 的場景。

我們同樣對比一下性能。

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

初步結論:加上 track_total_hits,檢索會變慢,我們要結合業務場景謹慎使用。

2.4 問題4:track_scores 确認是否必要使用!

track_scores 含義如下:When sorting on a field, scores are not computed. By setting track_scores to true, scores will still be computed and tracked.

也就是說這是個和排序相關的參數,如果走排序,就不計算評分。

如果想對排序加上評分處理,需要加這個參數。

2.5 問題5:"_source": {"includes": [ 确認是否必須

其實有更快的模組化方式,就是 store 設定 true 對字段單獨模組化。當然,這涉及到資料模組化和寫入。

_source 下召回的資料字段越多,肯定會越慢。暫且不說别的,網絡傳輸的角度就可見一斑。

網絡傳輸中,網速一定,但是 _source 字段多,意味着傳輸的位元組數多,必然會越慢。

還是拿微網誌資料驗證一下,

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

初步結論,僅指定一個字段比全部預設字段(10個以上),影響時間要快很多!

2.6 問題6:match,match_phrase, wildcard 都混合使用,考慮分詞問題解決。

推薦:字詞混合索引方案。

一個線上問題引發的思考——Elasticsearch 8.X 如何實作更精準的檢索?

2.7 問題7:建議線上使用複雜DSL,可以使用性能測試驗證一下。

文中 JMeter 測試工具使用,推薦視訊:

https://t.zsxq.com/0853Q9epD

3、小結

不要小瞧 DSL 的使用,不要堆砌一些不太了解的參數不加驗證直接用于實戰環境,後面的風險會變得很大。

Elasticsearch 8.X DSL 如何優化更有助于提升檢索性能?

DSL 的調優其實直接影響到檢索性能。

繼續閱讀