es性能優化沒有銀彈!
(1)性能優化的殺手鐧——filesystem cache (即 os cache,操作系統的緩存)
es的搜索引擎嚴重依賴於底層的filesystem cache,
你如果給filesystem cache更多的內存,盡量讓內存可以容納所有的indx segment file索引數據文件,那么你搜索的時候就基本都是走內存的,性能會非常高。
比如說,你一共要在es中存儲1T的數據,那么你的多台機器留個filesystem cache的內存加起來綜合,至少要到512G,
至少半數的情況下,搜索是走內存的,性能一般可以到幾秒鍾,2秒,3秒,5秒
如果最佳的情況下,filesystem cache 的大小 大於 ES所需要搜索的數據大小。
ES中只寫入需要索引的那幾個字段,不要把整條記錄都寫到 ES中。
比如說,ES就寫入 id name age三個字段就可以了,然后你可以把其他的字段數據存在hbase或mysql中,建議是HBase。
hbase的特點是適用於海量數據的在線存儲,就是對hbase可以寫入海量數據,不要做復雜的搜索,就是做很簡單的一些根據id或者范圍進行查詢的這么一個操作就可以了
從es中根據name和age去搜索,拿到的結果可能就20個doc id,然后根據doc id到hbase里去查詢每個doc id對應的完整的數據,給查出來,再返回給前端。
(2)數據預熱
es集群中每個機器寫入的數據量還是超過了filesystem cache一倍,
最好做一個專門的緩存預熱子系統,
就是將系統經常會被搜索的數據,每隔一段時間,你就提前訪問一下,讓數據進入filesystem cache里面去。
(3)冷熱分離
假設你有6台機器,2個索引,一個放冷數據,一個放熱數據,每個索引3個shard
3台機器放熱數據index;另外3台機器放冷數據index。
你大量的時候是在訪問熱數據index,熱數據可能就占總數據量的10%,此時數據量很少,幾乎全都保留在filesystem cache里面了,就可以確保熱數據的訪問性能是很高的。
但是對於冷數據而言,是在別的index里的,跟熱數據index都不再相同的機器上。
如果有人訪問冷數據,可能大量數據是在磁盤上的,此時性能差點,就10%的人去訪問冷數據;90%的人在訪問熱數據。
(4)document模型設計
es里面的復雜的關聯查詢,復雜的查詢語法,盡量別用,一旦用了性能一般都不太好。
document模型設計是非常重要的,很多操作,不要在搜索的時候才想去執行各種復雜的亂七八糟的操作。
es能支持的操作就是那么多,不要考慮用es做一些它不好操作的事情。
如果真的有那種操作,盡量在document模型設計的時候,寫入的時候就完成。
另外對於一些太復雜的操作,比如join,nested,parent-child搜索都要盡量避免,性能都很差的。
比如:如果要做order 與 orderItem的join操作,
最好在寫入es的java系統里,就完成關聯,將關聯好的數據直接寫入es中,
搜索的時候,就不需要利用es的搜索語法去完成join來搜索了。
總之,兩點:
1)在寫入數據的時候,就設計好模型,加幾個字段,把處理好的數據寫入加的字段里面
2)自己用java程序封裝,es能做的,用es來做,搜索出來的數據,在java程序里面去做,比如說我們,基於es,用java封裝一些特別復雜的操作
(5)分頁性能優化
es的分頁是較坑的,為啥呢?
假如你每頁是10條數據,你現在要查詢第100頁,實際上是會把每個shard上存儲的前1000條數據都查到一個協調節點上,如果你有個5個shard,那么就有5000條數據,接着協調節點對這5000條數據進行一些合並、處理,再獲取到最終第100頁的10條數據。
你翻頁的時候,翻的越深,每個shard返回的數據就越多,而且協調節點處理的時間越長。
用es作分頁,很可能會發生這種現象:前幾頁就幾十毫秒,翻到10頁之后,幾十頁的時候,基本上就要5~10秒才能查出來一頁數據了。
解決方法:
a、不允許深度分頁
b、如果不是那種允許隨意跳轉到某頁的那種分頁,而是手機上那種(下拉刷微博)只能往下一頁翻的那種分頁,可以用scroll api。
無論翻多少頁,性能基本上都是毫秒級的。
scroll的原理實際上是保留一個數據快照,然后在一定時間內,你如果不斷的滑動往后翻頁的時候,類似於你現在在瀏覽微博,不斷往下刷新翻頁。
那么就用scroll不斷通過游標獲取下一頁數據,這個性能是很高的,比es實際翻頁要好的多的多。
scroll是要保留一段時間內的數據快照的,你需要確保用戶不會持續不斷翻頁翻幾個小時。
os cache,操作系統的緩存
