經過一個搜索的場景來深刻剖析一下,當一個filter搜索請求打到Elasticsearch的時候,ES會進行下面的操做:數組
以date來舉例:緩存
word doc1 doc2 doc3 2019-01-01 * * 2019-02-02 * * 2019-03-03 * * *
filter: 2019-02-02
到倒排索引中一找,發現2019-02-02對應的document list是doc2,doc3數據結構
這一步是很是重要的,使用找到的doc list,構建一個bitset,就是一個二進制的數組,數組的每一個元素都是0或1,用來標識一個doc對一個filter條件是否匹配,若是匹配的話值就是1,不匹配值就是0。
因此上面的filter的bitset的結果就是:elasticsearch
[0,1,1]
doc1:不匹配這個filter的
doc2和doc3:匹配這個filter的
注意:這樣作的好處就是儘量用簡單的數據結構去實現複雜的功能,能夠節省內存空間,提高性能。性能
因爲一次性能夠在一個search請求中發出多個filter條件,那麼就會產生多個bitset,遍歷每一個filter條件對應的bitset優先從最稀疏的開始遍歷code
[0,0,0,0,0,0,0,1] 比較稀疏的bitset [1,0,1,1,0,1,0,1]
這裏主要是由於先遍歷比較稀疏的bitset,就能夠先過濾掉儘量多的數據排序
caching bitset會跟蹤query,在最近256個query中超過必定次數的過濾條件,緩存其bitset。對於小segment(<1000 或<3%),不緩存bitset。這樣下次若是在有這個條件過來的時候,就不用從新掃描倒排索引,反覆生成bitset,能夠大幅度提高性能。索引
說明:
一、在最近的256個filter中,有某個filter超過了必定次數,這個次數不固定,那麼elasticsearch就會緩存這個filter對應的bitset
二、filter針對小的segment獲取到的結果,是能夠不緩存的,segment記錄數小於1000,或者segment大小小於index總大小的3%。由於此時segment數據量很小,哪怕是掃描也是很快的;segment會在後臺自動合併,小segment很快會跟其它小segment合併成大segment,此時緩存就沒有什麼意思了,segment很快會消失。內存
query: 會計算每一個doc的相關度分數,還會根據這個相關度分數去作排序
filter: 只是簡單過濾出想要的數據,不計算相關度分數,也不排序it
這個過程是ES內部作的,好比以前的bitset是[0,0,0,1]。那麼如今插入一條數據或是更新了一條數據doc5,並且doc5也在緩存的bitset[0,0,0,1]的filter查詢條件中,那麼ES會自動更新這個bitset,變爲[0,0,0,1,1]
這樣查詢性能就會很高,一些熱的filter查詢,就會被cache住。