Elasitcsearch索引優化

2021-09-11 09:52:13 字數 3322 閱讀 4504

mac os下用homebrew安裝自己寫的開源工具

elasticsearch(下面簡稱es)本身的搜尋效能已經非常優秀,預設引數也適用於大部分場景;但為了更高效地利用計算資源,或者防止出現乙個請求消耗掉集群所有的資源情況,我們會對一些引數進行調優和限制。

常用的引數,預設使用lz4壓縮演算法,優點是壓縮速度非常快,對於寫入速度要求比較高,有充裕的儲存空間和讀寫速度的儲存介質的場景使用。

將該設定改為best_compression可使用deflate演算法來獲得更高的壓縮率,但會使用更多的cpu資源和時間來壓縮/解壓。通常都將該引數設為best_compression,除非寫入時cpu成為瓶頸。

該設定可在索引建立時或者處於close狀態的索引上指定,新的壓縮演算法將在下一次merge後生效。

另乙個常用的引數,增加索引分片數可提高搜尋的併發度。當乙個query分發到不同分片上時,es會將充分利用多核心cpu的優勢,每個分片使用不同的核心來處理搜尋請求;通常來說,分配到乙個節點上的主副分片之和等於cpu核心數將獲得最大的cpu利用率和最短的搜尋耗時。但分片數過多也會在合併搜尋結果時帶來額外的計算量,同時若其他的索引也在進行搜尋的會造成上下文切換,因此搜尋耗時不會隨著分片數增長而線性減少。

在滿足搜尋延遲的前提下,設定最小的分片數是最佳的選擇(暫時不考慮分片大小)。

也乙個常用的引數,用於調整寫入時的重新整理間隔,重新整理(refresh)既是將記憶體中的資料寫到檔案系統緩衝中;寫入的資料在重新整理後才能被搜尋,這也是es被稱為近實時搜尋的原因。其本質是segment的生成間隔。增大重新整理間隔可以減少segment的生成,同時也能減少搜尋耗時。通常將該值設為"30s",對實時性要求較高的索引可適當減少重新整理間隔。

因為segment無法做到實時生成,如果在兩次refresh間隔中節點宕掉,會導致資料丟失。translog的存在則是為了解決這個問題。translog中記錄了每一次對es的操作,預設是每個請求(bulk, delete, upadte, etc)完成後,或者達到同步間隔(sync_interval,預設5s)都會將日誌持久化(fsync)到磁碟中,當主副分片都確認持久化完成後,客戶端才會受到請求成功的響應;若節點出現異常,可以重放translog中在最後一次重新整理後發生的變更操作來恢復資料。

但是每次執行fsync會帶來少許的效能損失,若可以接受幾秒鐘的資料損失,可以將該引數設為"async",使用非同步fsync來減小translog帶來的影響。

當某個節點離線後,預設情況下1m後就會執行重建副本。當我們預知短時間內離線的節點能夠重新加入集群,可以延長重建副本的延時,來避免不必要的分片拷貝。

可使用put /_all/_settings來對集群中現有的所有索引應用該引數,該引數值視節點重啟的時間而定,通常可設為"5m"。

es缺省會使用max(1, min(4, cpu核心數 / 2))的執行緒數來進行merge操作,這會降低機械硬碟的讀寫效率,如果索引儲存在機械硬碟上,可將該值固定為"1"。

動態對映一方面降低了使用者的使用成本,另一方面也對集群管理造成了不便——由於不規範的稀疏的資料導致索引中的字段數大幅增長而影響搜尋效能。如果對乙份資料規範性要求比較高,可以通過將該引數設為"false"來關閉自動生成字段對映的特性。

以我們線上使用的經驗來看,es5.x(6.x的情況有待觀察)的分片分配機制不夠完善。當某個節點新加入集群的時候,會優先把大索引的分片和當天正在寫入的索引的大部分分片分配到該節點上,導致該節點的負載飆高。通過設定該引數可限制索引在該節點上的最大分片數,一定程度上避免這種情況的發生。

但是這個引數不能剛好設定為( pri_shard_num + rep_shard_num) / data_node_num,如果恰好設定成這個值,可能會出現最後乙個分配的副本和主分片在同一節點上,導致分配不上去。

若您大部分的搜尋請求是基於一定順序取topn,例如看最近的10條日誌,耗時最長的100個請求,或者交易最頻繁的5個使用者等等,es預設情況下會掃瞄全部資料後在返回結果。在es6.x中加入了乙個特性,能夠大幅降低這類搜尋的耗時:index sorting。若啟用該特性,es在寫入時候就會按照一定順序排列資料,例如按時間倒敘,這樣在搜尋的時候就不要掃瞄全量資料,只要獲得每個segment前topn的資料即可返回結果。該特性需要在索引建立的時候啟用,方法如下:

put log

},...

}複製**

注意,啟用該特性會降低寫入速度,因此需要在寫入和搜尋之間進行權衡。

"doc": }]

}}複製**

對於keyword型別的字段,如果我們只需要對該字段進行搜尋,不需要進行聚合、排序或是使用指令碼操作,可以將doc_value設為false,可大幅降節省磁碟空間,一定程度上提公升索引速度。

如果我們只需要對某個字段進行聚合、排序或是使用指令碼操作,不需要搜尋該欄位(通常是keyword或者numeric型別的字段),可以將index設為false,可釋放該欄位倒排索引占用的常駐記憶體。

索引的倒排索引占用的記憶體可通過get //_stats?human=true中的segments.terms_memory檢視。

norms引數對搜尋評分很有用,若我們不需要計算欄位的評分,將該引數設為false,特別是該字段僅用於過濾或聚合。若索引中存在某個字段啟用了norms,無**檔中是否存在該欄位,所有文件都會占用n bytes(n為文件數)磁碟空間,因此禁用norms可以釋放大量的磁碟空間。

norms可以通過以下api禁用,將在生成新的segment時生效,但不能被重新啟用。

}}複製**

在一些情況下,我們只需要儲存某個字段,通過搜尋其他的字段來定位到這條記錄檢視這個欄位的內容,不需要對該字段進行搜尋、排序、聚合等操作,可以將該字段的"enabled"設為false,同時節省大量記憶體和磁碟的空間。

我們經常碰到一些內容不規範或者格式不對的資料,例如某個ip欄位的裡出現"unknown",某個數字字段出現"-"。如果在這些欄位上已經設定了明確的型別,比如"ip"或者"float",字段**現了非該型別的值,es會丟擲異常並丟棄整條資料。

我們可以在該字段上設定"ignore_malformed": ture來忽略這個欄位並保留該文件中的其他字段。

該欄位屬於索引的元資料,其中儲存了文件原始的json內容,會被儲存但不會被索引,用於執行fetch請求時返回原始資料。

當我們不需要獲得任何原始資料,只需要對資料進行排序,聚合等計算,或者寫入時文件id是手動指定的,通過搜尋取到文件id來進一步處理,可以將"_source"設為false來節約大量的磁碟空間。

注意,禁用"_source"後會導致無法使用update,update_by_query,reindex等需要獲取原始文件的api,也無法使用高亮功能。

一些比較常用的針對索引級別的設定就介紹到這裡,某些在es6.x以上的版本已被棄用的引數將不再贅述。通過靈活地配置引數可將es的效能發揮到更高的水平。

索引,復合索引

這裡只看btree索引,至於雜湊索引和全文索引本文暫不討論。前言 索引是有效使用資料庫的基礎,但你的資料量很小的時候,或許通過掃瞄整表來訪問資料的效能還能接受,但當資料量極大時,當訪問量極大時,就一定需要通過索引的輔助才能有效地訪問資料。一般索引建立的好壞是效能好壞的成功關鍵。使用innodb作為資...

正向索引 反向索引 B Tree索引

索引就是為了更快的找出需要的資訊。一般都要進行排序。正向索引 開發出來用來儲存每個文件的單詞的列表。實際上,時間 記憶體 處理器等等資源的限制,技術上正向索引是不能實現的。既 儲存乙個文件中有那些單詞。有多少單詞就有多少列。然後對每一列進行某種排序。反向索引 其中每條記錄,記錄的是乙個單詞都在那些文...

DB索引 索引覆蓋 索引優化

索引 see 聚集索引 clustered index 聚集索引決定資料在磁碟上的物理排序,乙個表只能有乙個聚集索引,一般用primary key來約束。舉例 t user場景中,uid上的索引。非聚集索引 non clustered index 它並不決定資料在磁碟上的物理排序,索引上只包含被建立...