Elasticsearch是非常靈活且功能豐富的搜索引擎,提供了開箱即用的美好體驗。但是,在實戰業務場景中,經常會出現遠遠低于預期的索引和查詢速度。
下面是針對Elasticsearch索引性能進行調優的建議。
一、使用批量請求(bulk requests)
批量請求將產生比單文檔索引請求好得多的性能。
為了知道批量請求的最佳大小,嘗試在具有單個分片的單個節點上運行基準測試。 首先嘗試索引100個文檔,然后是200,然后是400,等等。 當索引速度開始穩定時,就達到了數據批量請求的最佳大小。
一般而言,寧可批量索引文檔少一些,而不是在太多文檔的方向上犯錯。 請注意,如果批量請求文檔太大,可能會使Elasticsearch集群受到內存壓力,因此建議避免每個請求超出幾十兆字節,即使較大的請求看起來效果更好。
二、使用多個工作者(workers)或線程向Elasticsearch發送數據
發送批量請求的單個線程不太可能將Elasticsearch集群的索引容量最大化。 為了使用集群的所有資源,可以從多個線程或進程發送數據。 除了更好地利用集群的資源,這應該有助于降低每個fsync的成本。
請注意TOO_MANY_REQUESTS(429)響應代碼(JAVA客戶端的EsRejectedExecutionException),這是Elasticsearch提示無法跟上當前索引速率的方式。 發生這種情況時,應該再次嘗試暫停索引,理想情況下使用隨機策略調整索引并發量。
與調整批量請求(bulk request)大小類似,只有測試才能確定最佳的worker數量。 這可以通過逐漸增加工作者數量來測試,直到集群上的I/O或CPU飽和。
三、調大refresh interval參數
為了讓索引文檔對查詢可見,需要執行refresh操作,該操作是有成本的。當正在進行索引時,不斷地執行refresh操作,將影響索引速度。
默認的index.refresh_interval是1s,這迫使Elasticsearch每秒創建一個新的分段。 增加這個參數值(比如說30s)將提升索引速度。
PUT INDEX-NAME/_settings
{
"refresh_interval" : "30s"
}
四、初始化數據加載臨時禁用refresh和replicas
如果需要一次加載大量數據,則應該將index.refresh_interval設置為-1,并將index.number_of_replicas設置為0,來禁用刷新(refresh)。這會暫時使索引處于危險之中,因為任何分片的丟失都將導致數據丟失,但是同時索引將會更快,因為文檔只被索引一次。初始加載完成后,可以將index.refresh_interval和index.number_of_replicas設置回其原始值。
五、禁用swApping交換內存
通過禁止swap交換內存,確保操作系統不會交換出Java進程。
具體禁用swapping的操作,可以參考下面鏈接:
https://www.elastic.co/guide/en/elasticsearch/reference/7.0/setup-configuration-memory.html
六、提供內存給filesystem cache
文件系統緩存(filesystem cache)將用于緩沖I/O操作。 確保運行Elasticsearch的節點獲得至少一半的主機內存,提供給filesystem cache。
七、使用自動生成的id(auto-generated ids)
索引具有顯式id的文檔時,Elasticsearch需要檢查具有相同id的文檔是否已經存在于相同的分片中,這是費時的操作,并且隨著索引增長而變得更加費時。 通過使用自動生成的ID,Elasticsearch可以跳過這個檢查,這使索引更快。
PUT test-index
{
"settings":{
"number_of_shards": 3,
"number_of_replicas": 1
}
}
POST test-index/_doc
{
"sku": "002",
"title": "bbb"
}
GET test-index/_search
八、使用更快的硬件
一般而言,索引是I/O密集的,需要準備如下硬件:
(1)為filesystem cache分配更多的內存;
(2)使用SSD硬盤;
(3)使用local storage(不要使用NFS、SMB 等remote filesystem)
九、索引緩存區(Indexing buffer size)
如果節點只做大量的索引,確保index.memory.index_buffer_size足夠大,每個分片最多可以提供512 MB的索引緩沖區。超過這一設置,索引性能通常也不會提升。
Elasticsearch采用該設置(Java堆的百分比,或者絕對字節大小),并將其作為所有活動分片(active shards)的共享緩沖區。非常活躍的分片自然比執行輕量級索引的分片,更多地使用這個緩沖區。
默認設置為 10%,通常是足夠的。如我們給JVM 10GM內存,索引緩沖區將為1GB,這足以兩個索引很重的分片。