這裏有一篇很好的文章,很不錯,翻譯和整理了一下,英文不錯的,建議直接看原文:http://euphonious-intuition.com/2013/05/all-about-elasticsearch-filter-bitsets/數組
elasticsearch裏面有BOOL filter、AND、OR、NOT filter,這幾個看起來很類似,都有什麼區別呢?何時用boolfilter?何時用AND filter呢?緩存
事實上,bool filter和AND 、OR、NOT filter 是徹底不一樣,在查詢性能上面的影響是很是大的。bash
首先我們須要瞭解的是filter裏面都是怎麼工做的,其中核心的一個東西叫BitSet,能夠理解爲一個很大的bit數組,數組裏面的每一個元素有2個狀態:0和1(bloom filter知道麼?),而filter你們都知道,只處理文檔是否匹配與否,不涉及文檔評分操做。若是一個文檔和filter查詢匹配,那麼其對應的bit位就設置爲1,匹配不上則設置爲0。數據結構
es在執行filter查詢過濾的時候,會打開lucene的每一個segment段文件,而後去判斷裏面的文檔符合該filter與否,這個匹配的結果咱們就能夠用bitset來存儲起來,下次一樣的filter查詢過來,咱們就直接使用內存裏面的bitset來進行判斷就好了,而不須要再打開lucene的segment文件了,避免了io的操做,這樣就能夠大大提升查詢處理的速度,這也是爲何filter這麼高效的緣由。app
由於lucene的segment段文件是不變的,lucene會產生新段,可是舊段是不變的,因此bitset是重複利用的,根據不一樣的filter條件和不一樣的段,會產生相應的bitset,另外不一樣的查詢可能會涉及到多個bitset的作交集,計算機對這種bit位處理過程是很是拿手的,速度很快。elasticsearch
另外,若是filter的結果若是是空的,那麼裏面的bitset位都是0,es之後在處理該filter的時候,會把該bitset整個忽略掉,提升性能。ide
前面說完了基礎內容,我們再看看bool filter和AND filter這些的區別吧性能
bool filter會使用到前面提到過的bitset數據結構(bitset派),而AND \OR\ NOTfilter則不能利用到bitset(non-bitset派),爲何呢?ui
AND、OR、NOT filter是doc by doc的逐個文檔的處理,es逐個加載文檔裏面的字段內容,而後檢查字段的內容是否知足查詢條件,不知足的文檔就排除在結果集以外,依次迭代進行,直到過完一遍全部的文檔,這中間的過程用不到前面提到過的bitset,也就不能重複利用緩存資源.net
若是你有多個filter條件,即一個AND、OR、NOT裏面包含多個filter過濾條件(支持數組的方式),那麼處理的邏輯就是每一個filter會將依次將生成的結果集傳到下一個filter,理論上處理的文檔數會愈來愈少,由於只會過濾減小,不會增長,這樣依次過濾,因此通常限制條件比較苛刻的能夠放前面執行,這樣後面的filter須要處理的文檔數就會很小,這樣能夠大大提升總體處理的速度,另外除了數量上的考慮外,還須要考慮filter的效率問題,一些filter執行效率很低,如Geo filter(大量計算)或者script based filter(動態腳本),建議將這些性能開銷比較大的查詢放最後執行來提升總體的處理速度。
好了,如今應該有這麼一個概念了,AND、OR、NOT是文檔by文檔,依次處理,若是你的結果集很大,即一個很寬鬆的查詢,命中不少,那麼你使用AND、OR、NOT filter是不合適的,可是有些filter是必須文檔by文檔處理的,以下面的這幾個filter:
因此除了上面那幾個沒有辦法的,其它的filter應該一概使用bool filter來提升查詢性能。
若是你的查詢裏面須要同時使用到bitset和non-bitset類型的filter,則能夠組合起來使用bool filter和AND\OR\NOT filter,
前面說了,AND 是結果集依次向後傳遞,因此咱們把性能比較好的放前面,non-bitset放AND的filter的後面,以下面一個包含多個filter類型的複雜的filter
{ "and" : [ { "bool" : { "must" : [ { "term" : {} }, { "range" : {} }, { "term" : {} } ] } }, { "or" : [ { "custom_script" : {} }, { "geo_distance" : {} } ] } ] }
and 在最外層作wrapper,第一個filter是一個bool filter,裏面有3個must的子filter,處理完了以後,獲得文檔結果集,而後再執行一個or的子filter,OR裏面兩個查詢會分別進行,最終的文檔結果集就是咱們的搜索結果了。
總之,filter使用的時候,必定要優先使用bitset流,而後還要考慮filter順序和組合的問題
掌握了以上這些,就不難寫出高性能的查詢了。
本文出自:http://log.medcl.net/item/2013/09/elasticsearch-inside-the-various-filter/