Elasticsearch 調優 (官方文檔How To)

How To

Elasticsearch默認是提供了一個很是簡單的即開即用體驗。用戶無需修改什麼配置就能夠直接使用全文檢索、結果高亮、聚合、索引功能。java

可是想在項目中使用高性能的Elasticsearch,有幾方面優化方法最好掌握。數據庫

本文就是爲了引導如何優化。api

常規建議

不要一次返回太大量的搜索結果集

Elasticsearch設計做爲一個搜索引擎,很是擅長返回匹配的查詢結果。可是,它並不合適像數據庫同樣,把整個document做爲查詢結果返回。若是非要這樣作,最好仍是使用Scroll這個接口來。緩存

避免索引稀疏

Elasticsearch是基於Lucene進行索引和存儲數據的,最佳的工做方式是密集的數據,便是全部的document擁有相同的字段。特別是啓用了norms(一般是text字段是默認開啓)或者啓用了doc_values(一般是numerics, date, ip 或 keyword 是默認開啓)的字段。數據結構

緣由是Lucene內部是經過由0到索引 document 總數的 doc_id 來識別 document 。doc_id 用於Lucene api內部之間的通信:例如使用關鍵詞 match 查詢獲得的doc_id,而後這些doc_id用於檢索 norms 的值去計算 score(匹配得分)。這個 norms 查找方式實現目前是經過爲每一個 document 保留一個字節。doc_id 能夠直接讀取該 document 的 norms 值。這種方式好處是能夠幫助Lucene快速訪問每一個 document ,缺點是每一個 document 還須要額外佔多一個字節的存儲。多線程

實際上,這就意味着若是一個index裏面有M個document,每一個字段的norms就須要M個字節的存儲,就算某些字段只是包含在小部份 document 。雖然複雜的類型字段存儲使用doc_values,可是同樣還會佔用存儲的。衆所周知,fielddata 類型在 pre-2.0以後被替換成 doc_values ,除非 fielddata已經寫在硬盤上了,在內存裏面的話,也是有這個問題。併發

須要注意的是,稀疏存儲會對索引和搜索速度有明顯的影響,額外的存儲字節雖然不是字段,也是須要花費時間去索引和搜索的。app

固然,index是容許存在少數稀疏狀況的,可是若是稀疏數量教大,則會影響整個index的效率。性能

本章節主要集中在 norms 和 doc_values 這兩個影響較大的特性。稀疏狀況會影響倒排索引(用於索引 text/keyword 字段)和座標點類型字段(用於索引 geo_point 和 numeric),影響的程度不同。測試

下面有幾點推薦能避免稀疏:

避免把無關聯的數據放在同一個index

不要把徹底不一樣的數據結構 document 放在同一個 index 裏面。最好是將這些 document 放到不一樣的index裏面,能夠考慮建立一些較小的index, 用較少的shard去存儲。

注意,這個建議不適用於有使用 parent/child 這種帶關係的 document 放在同一個 index 的狀況。

標準化 document 結構

若是必需把不一樣類型的 document 放在同一個 index裏面,也是有機會減小稀疏狀況的。例如,在 index 內全部的 document 都添加一個時間戳字段,一般叫"timestamp"或者"creation_date",它將會有助於把全部的 document 重命成相同的字段。

避免不一樣的 type 放在同一個index

多個 type 放在單個 index 看起來是個簡單的方法。可是Elasticsearch並非基於 type來存儲的,不一樣的 type 在單個 index 也會影響效率。若是 type 沒有很是類似的 mapping,建議考慮放到一個單獨的 index 上面。

對於不一樣的字段禁用 norms 和 doc_values

若是以上建議適用,還須要檢查字段是否啓用了 norms 和 doc_values。一般只用於過濾而不須要進行打分(匹配度打分)的字段,能夠直接禁用 norms 。不用於排序或者聚合的字段能夠禁用 doc_values 。注意,若是在已有的 index 作這些變動,是須要對 index 作 reindex的動做。

調優索引速度

使用 bulk 請求

Bulk 批量請求比單次 document 索引請求性能更好。爲了驗證最優批量請求的大小,能夠作一個基準測試,用一個單節點跑一個單 shard 。先嚐試索引100個document,而後 200, 而後400,等等。每次運行基準測試就相應加倍 document 的數量。取得索引速度最高的數值,就是最佳的bulk批量請求數。固然,批量請求也不是越多 document 越好。若是併發同時請求,太大的 bulk 請求會使集羣內存壓力變大,因此建議避免每次請次超過幾十M,這樣會得到較好的性能。

使用多進程/多線程去發送數據到Elasticsearch

一個單線程發送 bulk 請求彷佛不可以發揮一個集羣的索引能力。爲了更好地利用集羣的資源,應該使用多線程或多進程來發送數據,同時這將有助於減小每次 fsync 的成本。

必定要留意系統是否返回 TOO_MANY_REQUESTS (429) 代碼。(一般Java client返回是EsRejectedExecutionException),這是表示Elasticsearch沒法跟上當前的索引速度。發生這種狀況時能夠暫停一下索引一會再試。嘗試更換 bulk 一個隨機值或理想值。

對於相同大小的 bulk 請求,經過測試能夠獲得最優的線程數量。能夠逐步增長線程數量直至到集羣中的機器IO或CPU飽和。

增長 refresh_interval 刷新的間隔時間

index.refresh_interval的默認值是 1s,這迫使Elasticsearch集羣每秒建立一個新的 segment (能夠理解爲Lucene 的索引文件)。增長這個值,例如30s,能夠容許更大的segment寫入,減後之後的segment合併壓力。

在初始化索引時,能夠禁用 refresh 和 replicas 數量

若是須要一次加載較大的數據量進 index 裏面時,能夠先禁用 refresh ,把 index.refresh_interval 設置成爲 -1 ,把 index.number_of_replicas 設置成 0。暫時把多個shard副本關閉(即若是當前index發生損壞便用丟失數據),可是這樣作能夠大大加快索引速度。當初始化索引完成,能夠將 index.refresh_interval 和 index.number_of_replicas 設置回原來的值。

禁用 swapping

把操做系統的虛擬內存交換區關閉。sysctl 裏面添加 vm.swappiness = 1

確保有空閒的內存給文件系統緩存

文件系統緩存是爲了緩衝磁盤的IO操做。至少確保有一半機器的內存保留給操做系統,而不是JAVA VM佔用了所有內存。

使用更快的硬件

固然這個不用說了上SSD是最好的了。若是有多個SSD硬盤,能夠配置成 RAID 0陣列取得更佳的IO性能。可是任何一個SSD損壞都有可能弄壞 index。一般正確的權衡是優化單的shard存儲性能,而後添加 replicas 放在不一樣的節點。同時使用 snapshot 快照和 restore 功能去備份 index。

索引 buffer 大小

若是節點在作很是大的索引動做,須要確保 indices.memory.index_buffer_size足夠大,最多能夠設置爲512M的buffer。除此以外增長這個值,性能一般不會獲得改善。

Elasticsearch的活躍shard須要使用java的heap內存的百份比或者絕對值去做爲一個共享緩衝區。很是活躍的shard天然會使用較頻繁。

這個默認值是一般是10%,例如,若是JVM設置爲10GB內存爲heap,那麼就會有1GB的索引緩衝區提供給大量的索引shard。

相關文章
相關標籤/搜索