Elasticsearch查詢性能優化



加配置項index.merge.policy.floor_segment=設置每個segment最小值,index.merge.scheduler.max_thread_count=ES集群負載較低時,后台合並segment線程數,一般=核數/2;
curl -XPUT http://xxxx:9200/m_pd_cu_id_ip_2es_inc_hi_out/_settings -d '{"index.merge.policy.floor_segment":"100mb"}'
curl -XPUT http://xx:9200/m_pd_cu_id_rela_address_2es_dt_out/_settings -d '{"index.merge.scheduler.max_thread_count":"2"}'
原因分析:數據同步服務不斷的在提交索引構建,ES集群接收到構建請求數據后會緩沖到內存,達到一定量后生成segment,每個segment是一個包含正排(空間占比90~95%)+倒排(空間占比5~10%)的完整索引文件,每次搜索請求會將所有segment中的倒排索引部分加載到內存,進行查詢和打分,然后將命中的文檔號拿到正排中召回完整數據記錄;如果不對segment做配置,提交又特別頻繁的話,就會導致查詢性能下降,另外將這里的普通硬盤換成SSD,預計搜索性能還會提升3~5倍;

【總結】
搜索性能優化建議:
1.segment合並;索引節點粒度配置index.merge.policy.floor_segment=xx mb;segment默認最小值2M
2.索引時不需要做打分的字段,關閉norms選項,減少倒排索引內存占用量;字段粒度配置omit_norms=true;
3.BoolQuery 優於 TermQuery;目前需求場景全部不需要用到分詞,所以盡可能用BoolQuery;
4.避免使用對象嵌套結構組建document,建議優化為一個扁平化結構,查詢多個扁平化結構在內存做聚合關聯;
5.設定字符串類型為不分詞,可以用於字符串排序,但是比起數字排序會消耗cpu,搜索效率更低,慎用;
6.cache設置,就目前數據業務類型,保持默認配置即可,設值fielddata.cache之類的緩存命中率低,反而吃掉了ES集群的一部分內存;

索引性能優化建議:
1.調小索引副本數;針對索引節點粒度:curl -XPUT http://xxxx:9200/m_pd_cu_id_gps_2es_inc_hi_out/_settings -d '{"number_of_replicas":1}'
2.設置延遲提交,延遲提交意味着數據提交到搜索可見,有延遲,需要結合業務配置;針對索引節點粒度:curl -XPUT http://xxxx:9200/m_pd_cu_id_gps_2es_inc_hi_out/_settings -d '{"index.refresh_interval":"10s"}';默認值1s;
3.設置索引緩沖buffer,最大512m,默認值是jvm的10%;ES集群粒度config/elasticsearch.yml :indices.memory.index_buffer_size = 10%

4.適當減少備份數,必要字段只需要提供搜索,不需要返回則將stored設為false;

如果ES提交索引請求達到瓶頸,一般任務隊列task-queue為50,可以設置task-queue隊列,提升搜索集群索引能力;


以上涉及到索引節點/字段 粒度的配置,均可在創建時代碼指定;
————————————————
原文鏈接:https://blog.csdn.net/my201110lc/article/details/81712183

備注: segment合並的影響可能只有5%;現象:”發現每次搜索請求時,磁盤需要讀40M+的數據,然而一次請求的數據不過10+k“,這個是由於,es底層的lucene對文件的讀取采用了mmap方式,而你的機器內存不足以映射所有的文件,所以前幾次查詢時,會讀磁盤,而mmap讀取磁盤會默認預讀2M的數據量,這才是你請求10K的數據,卻有40M的io的真正原因,預讀的2M數據,假設有20條同步不在一個段上,那么就會產生40M的磁盤io。
解決這個問題的方法是設置這個參數:index.store.type為niofs,兩種方式,啟動時設置yml,對所有索引生效;或者在新建索引時指定settings中,對於已經建好的索引,必須先close,然后修改調用接口修改settings。再提一點,es默認的mmapfs其實是針對內存足夠的情況下使用的,也就是堆外內存能把所有的segment數據都加載進來。對於內存不足的情況,用niofs比較合適,因為它不會預讀,每次都走磁盤。

index.store.type 為 niofs

curl -XPUT 'http://localhost:9200/twitter/' -d '{
"settings" : {
"index" : {
"store":{
"type":"niofs"
},
"refresh_interval":"60s"

}
}
}'

 
Mmap fs可能讓大索引訪問變得緩慢:  https://elasticsearch.cn/article/754

總結:
  1. mmap fs對比nio fs,省去了磁盤io上的系統調用,並且不需要在jvm內部做io緩存,也減輕了GC壓力。 所以通常來說,mmapfs的性能應該更高。 這也是為什么lucene推薦使用mmap fs,並且ES從5.0開始做為默認的store配置的原因。
  2. 然而,mmap系統調用,在內核層面默認會有一個2MB的預讀大小設置,也就是說,當映射了一個大文件以后,即使讀取其中1k個字節,mmap也會預讀取2MB的數據到緩存。 這種策略是基於文件的訪問大多數是順序的假設。
  3. 在ES這個特定的應用場景,如果某數據結點上索引不是很大,系統剩余緩存也足夠,一般不會有問題。但是如果是大數據應用場景,典型的如海量的日志ELK應用,則可能對大索引的搜索聚合,產生較多的隨機磁盤訪問。 從而mmap的預讀策略,可能會導致大量的無用數據從磁盤讀取到系統緩存。 在系統可用的緩存不是非常寬裕的情況下,某些極端場景下,會導致熱數據被過於頻繁的踢出內存,再反復讀入,讓磁盤IO不堪重負。
  4. Lucene有一個NativePosixUtil.madvise(buffer,NativePosixUtil.RANDOM)的native調用,可以用於指導內核對mmap過的文件做讀取的時候,禁用預讀。 上文作者將該調用hack進lucene代碼,做搜索對比測試。 結論是對於磁盤io和cache的消耗,niofs都要好於mmapfs,而patch過的mmapfs則比niofs更好。
  5. 作者的測試僅限於搜索,對於其他類型的io操作,如寫入,merge沒有做過詳盡測試,因此不清楚利弊。
  6. ES官方開發人員認為這是一個有趣的發現,值得深入去探究。對於用戶報告的mmap fs性能比nio fs更差的問題,猜測可能是在大索引讀取的場景下,預讀帶來的額外開銷,抵消了相對niofs節省的系統調用等開銷。 
  7. ES官方提到Lucene已經有一種類似功能的store,叫做NativeUnixDirectory(顯然ES目前還沒有對這種store的支持),用戶動手能力強的話,應該可以利用這個store自己寫一個ES plugin。 另外提到JAVA 10提供了O_DIRECT to streams / channels ,似乎官方打算等這個出來以后再看怎么處理這個問題。
  8. 要注意,這個預讀是mmap層面的,和塊設備的預讀是兩回事。 我們曾經嘗試過使用 blockdev --setra 這個linux命令取消塊設備預讀,證實無法解決這個問題。
 
結論: 如果ES結點上會存放海量的索引數據,經常會有大索引(如1TB+)的搜索聚合操作,使用NIOFS會更安全,可以避免很多怪異的性能問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM