ES索引優化篇主要從兩個方面解決問題,一是索引數據過程;二是檢索過程。
索引數據過程我在上面幾篇文章中有提到怎么創建索引和導入數據,但是大家可能會遇到索引數據比較慢的過程。其實明白索引的原理就可以有針對性的進行優化。ES索引的過程到相對Lucene的索引過程多了分布式數據的擴展,而這ES主要是用tranlog進行各節點之間的數據平衡。所以從上我可以通過索引的settings進行第一優化:
"index.translog.flush_threshold_ops": "100000"
"index.refresh_interval": "-1",
這兩個參數第一是到tranlog數據達到多少條進行平衡,默認為5000,而這個過程相對而言是比較浪費時間和資源的。所以我們可以將這個值調大一些還是設為-1關閉,進而手動進行tranlog平衡。第二參數是刷新頻率,默認為120s是指索引在生命周期內定時刷新,一但有數據進來能refresh像lucene里面commit,我們知道當數據addDoucment會,還不能檢索到要commit之后才能行數據的檢索所以可以將其關閉,在最初索引完后手動refresh一之,然后將索引setting里面的index.refresh_interval參數按需求進行修改,從而可以提高索引過程效率。
另外的知道ES索引過程中如果有副本存在,數據也會馬上同步到副本中去。我個人建議在索引過程中將副本數設為0,待索引完成后將副本數按需量改回來,這樣也可以提高索引效率。
"number_of_replicas": 0
上面聊了一次索引過程的優化之后,我們再來聊一下檢索速度比較慢的問題,其實檢索速度快度與索引質量有很大的關系。而索引質量的好壞與很多因素有關。
一、分片數
分片數,與檢索速度非常相關的的指標,如果分片數過少或過多都會導致檢索比較慢。分片數過多會導致檢索時打開比較多的文件別外也會導致多台服務器之間通訊。而分片數過少為導至單個分片索引過大,所以檢索速度慢。
在確定分片數之前需要進行單服務單索引單分片的測試。比如我之前在IBM-3650的機器上,創建一個索引,該索引只有一個分片,分別在不同數據量的情況下進行檢索速度測試。最后測出單個分片的內容為20G。
所以索引分片數=數據總量/單分片數
目前,我們數據量為4億多條,索引大小為近1.5T左右。因為是文檔數據所以單數據都中8K以前。現在檢索速度保證在100ms 以下。特別情況在500ms以下,做200,400,800,1000,1000+用戶長時間並發測試時最壞在750ms以下.
二、副本數
副本數與索引的穩定性有比較大的關系,怎么說,如果ES在非正常掛了,經常會導致分片丟失,為了保證這些數據的完整性,可以通過副本來解決這個問題。建議在建完索引后在執行Optimize后,馬上將副本數調整過來。
大家經常有一個誤去副本越多,檢索越快,這是不對的,副本對於檢索速度其它是減無增的我曾做過實現,隨副本數的增加檢索速度會有微量的下降,所以大家在設置副本數時,需要找一個平衡值。另外設置副本后,大家有可能會出現兩次相同檢索,出現出現不同值的情況,這里可能是由於tranlog沒有平衡、或是分片路由的問題,可以通過?preference=_primary 讓檢索在主片分上進行。
三、分詞
其實分詞對於索引的影響可大可小,看自己把握。大家越許認為詞庫的越多,分詞效果越好,索引質量越好,其實不然。分詞有很多算法,大部分基於詞表進行分詞。也就是說詞表的大小決定索引大小。所以分詞與索引膨漲率有直接鏈接。詞表不應很多,而對文檔相關特征性較強的即可。比如論文的數據進行建索引,分詞的詞表與論文的特征越相似,詞表數量越小,在保證查全查准的情況下,索引的大小可以減少很多。索引大小減少了,那么檢索速度也就提高了。
四、索引段
索引段即lucene中的segments概念,我們知道ES索引過程中會refresh和tranlog也就是說我們在索引過程中segments number不至一個。而segments number與檢索是有直接聯系的,segments number越多檢索越慢,而將segments numbers 有可能的情況下保證為1這將可以提到將近一半的檢索速度。
$ curl -XPOST 'http://localhost:9200/twitter/_optimize? max_num_segments =1'
五、刪除文檔
刪除文檔在Lucene中刪除文檔,數據不會馬上進行硬盤上除去,而進在lucene索引中產生一個.del的文件,而在檢索過程中這部分數據也會參與檢索,lucene在檢索過程會判斷是否刪除了,如果刪除了在過濾掉。這樣也會降低檢索效率。所以可以執行清除刪除文檔。
$ curl -XPOST 'http://localhost:9200/twitter/_optimize? only_expunge_deletes =true'
