Elasticsearch裏面的segment合併

經過前面的文章,咱們已經知道在elasticsearch中每一個shard每隔1秒都會refresh一次,每次refresh都會生成一個新的segment,按照這個速度過不了多久segment的數量就會爆炸,因此存在太多的segment是一個大問題,由於每個segment都會佔用文件句柄,內存資源,cpu資源,更加劇要的是每個搜索請求都必須訪問每個segment,這就意味着存在的segment越多,搜索請求就會變的更慢。node

那麼elaticsearch是如何解決這個問題呢? 實際上elasticsearch有一個後臺進程專門負責segment的合併,它會把小segments合併成更大的segments,而後反覆這樣。在合併segments的時候標記刪除的document不會被合併到新的更大的segment裏面,全部的過程都不須要咱們干涉,es會自動在索引和搜索的過程當中完成,合併的segment能夠是磁盤上已經commit過的索引,也能夠在內存中還未commit的segment:api

(1)在索引時refresh進程每秒會建立一個新的segment而且打開它使得搜索可見elasticsearch

(2)merge進程會在後臺選擇一些小體積的segments,而後將其合併成一個更大的segment,這個過程不會打斷當前的索引和搜索功能。性能

image

(3)一旦merge完成,舊的segments就會被刪除,流程以下:優化

3.1 新的segment會被flush到磁盤

3.2 而後會生成新的commit point文件,包含新的segment名稱,並排除掉舊的segment和那些被合併過的小的segment

3.3 接着新的segment會被打開用於搜索

3.4 最後舊的segment會被刪除掉

image

至此原來標記僞刪除的document都會被清理掉,若是不加控制,合併一個大的segment會消耗比較多的io和cpu資源,同時也會搜索性能形成影響,因此默認狀況下es已經對合併線程作了資源限額以便於它不會搜索性能形成太大影響。線程

api以下:日誌

PUT /_cluster/settings
{
    "persistent" : {
        "indices.store.throttle.max_bytes_per_sec" : "100mb"
    }
}

或者不限制:code

PUT /_cluster/settings
{
    "transient" : {
        "indices.store.throttle.type" : "none" 
    }
}

es的api也提供了咱們外部發送命令來強制合併segment,這個命令就是optimize,它能夠強制一個shard合併成指定數量的segment,這個參數是:max_num_segments ,一個索引它的segment數量越少,它的搜索性能就越高,一般會optimize成一個segment。須要注意的是optimize命令不要用在一個頻繁更新的索引上面,針對頻繁更新的索引es默認的合併進程就是最優的策略,optimize命令一般用在一個靜態索引上,也就是說這份索引沒有寫入操做只有查詢操做的時候是很是適合用optimize來優化的,好比說咱們的一些日誌索引,基本都是按天,周,或者月來索引的,只要過了今天,這周或這個月就基本沒有寫入操做了,這個時候咱們就能夠經過optimize命令,來強制合併每一個shard上索引只有一個segment,這樣查詢性能就能大大提高,api以下:blog

POST /logstash-2014-10/_optimize?max_num_segments=1

注意,由外部發送的optimize命令是沒有限制資源的,也就是你係統有多少IO資源就會使用多少IO資源,這樣可能致使某一段時間內搜索沒有任何響應,因此若是你計劃要optimize一個超大的索引,你應該使用shard allocation功能將這份索引給移動到一個指定的node機器上,以確保合併操做不會影響其餘的業務或者es自己的性能。索引

相關文章
相關標籤/搜索