一、背景
每周統計接口耗時,發現耗時較長的前幾個接口tp5個9都超過了1000ms。
經過分析慢查詢的原因是ES查詢耗時太長導致的
二、設計方案
1、問題定位
查詢功能使用不當導致慢查詢
索引設計存在不合理的地方,導致慢查詢
2、方案概述
2.1、查詢Fetch Source優化
-
問題
業務查詢語句獲取的數據集比較大,並且從source中獲取了非必須的字段,導致查詢較慢。
舉例:只需要從es中查詢id這一個字段,卻把所有字段查詢了出來
-
分析
因為數據集較大,若每個字段都去source中獲取所需字段,會導致耗時嚴重增加,需要避免這種操作,可以大大降低es集群,網絡和客戶端的壓力,提高程序的性能。
-
優化方法
查語句查詢時,將fetchSource設置為false
2.2、查詢優化,調整filter過濾順序
-
問題
過濾效果不明顯的條件放在了前面,導致查詢出大量不需要的數據,導致查詢變慢
-
優化方法
把過濾效果明顯的條件提前,按照過濾效果把過濾條件排序
2.3、索引時間精度優化
-
分析
降低時間精度。研究Filter的工作原理可以看出,它每次工作都是遍歷整個索引的,所以時間粒度越大,對比越快,搜索時間越短,在不影響功能的情況下,時間精度越低越好,有時甚至犧牲一點精度也值得,當然最好的情況是根本不作時間限制。
-
優化方法
es重新刷索引,增加冗余的時間字段,精確到天。
帶有時間范圍的查詢使用該字段進行查詢
2.4、索引優化,合理使用keyword類型
-
分析
ES5.x里對數值型字段做TermQuery可能會很慢。
在ES5.x+里,一定要注意數值類型是否需要做范圍查詢,看似數值,但其實只用於Term或者Terms這類精確匹配的,應該定義為keyword類型。
ES 2.x -> 5.x升級對於數值類型和Term Query有何重大變化?
-
Lucene6.0引入了重新設計的數值類型的索引結構,不再采用倒排索,而是使用了更適合范圍查找的Block K-d Tree。 ES從5.0開始引入這種新結構
-
Term Query由於通常非常快,從5.1.1開始不再被緩存到Query Cache
有興趣的可以看一下詳細分析:https://elasticsearch.cn/article/446
-
-
優化方法
把不做范圍查詢的數值類型修改為keyword類型
3、reIndex索引
-
先在管理平台創建新索引模板。模板名:xxx_new,設置索引生成規則
-
在導數據之前將新索引副本數設為0,這樣導數據速度較快,導完數據再改為1 即可
-
通過腳本執行reIndex操作,需要記錄開始時間time
-
再次執行reIndex上次reIndex期間新寫入的增量數據(time減去時差8小時) ,這一步的寫入可能需要幾分鍾
-
操作動態配置,停止寫入ES數據,然后再次reindex這幾分鍾內寫入的增量數據,命令同上(這一次的寫入可能就幾秒鍾了)
-
刪除舊索引,並將新索引的別名設置為舊索引的名稱
-
開啟寫入ES開關,並且重新導入停止寫入ES期間的數據,並恢復各索引副本數為1。