Elastic Search中filter的理解


在ES中,請求一旦發起,ES服務器是按照請求參數的順序依次執行具體的搜索過濾邏輯的。如何定制請求體中的搜索過濾條件順序,是一個經驗活。
類似query(指search中的query請求參數),也是搜索的一種方式。與常見的搜索對比,filter不會計算搜索條件相關度分數,也不會根據相關度分數進行排序,相對效率更高一些。且filter內置cache,自動緩存常用的filter數據,有效提升過濾速度。語法:
GET /test_sort/_search
{
"query": {
"bool": {
"filter": {
"range": {
"order": {
"lt" : 20
}
}
},
"must": [
{
"match": {
"content": "second"
}
}
]
}
}
}
如果搜索數據需要對相關度進行排序,如百度搜索,使用搜索查詢。如果搜索數據對相關度無要求,建議使用filter來提升執行效率。通常來說,如果有多個條件的話,一般都會使用其中的部分條件做filter過濾,再執行query搜索,來提高效率。
如果是單純的過濾數據。不需要增加額外的搜索匹配(沒有任何的相關度分數計算的要求),也可以使用下述語句:
GET /test_sort/_search
{
"query": {
"constant_score": {
"filter": {
"range": {
"order": {
"lte": 20
}
}
}
}
}
}
5.1 fitler 底層執行原理(bitset機制和cache機制)
5.1.1 執行流程
首先我們假設某index中有document數據如下:
POST /_bulk
{ "create" : { "_index" : "test_filter" , "_type" : "filter_type", "_id" : "1" } }
{"field" : "2011 2012 2013"}
{ "create" : { "_index" : "test_filter" , "_type" : "filter_type", "_id" : "2" } }
{"field" : "2012 2013 2014"}
{ "create" : { "_index" : "test_filter" , "_type" : "filter_type", "_id" : "3" } }
{"field" : "2013 2014 2015"}
{ "create" : { "_index" : "test_filter" , "_type" : "filter_type", "_id" : "4" } }
{"field" : "2012 2014 2011"}
{ "create" : { "_index" : "test_filter" , "_type" : "filter_type", "_id" : "5" } }
{"field" : "2011 2012 2014"}
{ "create" : { "_index" : "test_filter" , "_type" : "filter_type", "_id" : "6" } }
{"field" : "2014 2012 2011"}
那么ES會創建的倒排索引如下:
Word Docs
"2011" 1, 4, 5, 6
"2012" 1, 2, 4, 5, 6
"2013" 1, 2, 3
"2014" 2, 3, 4, 5, 6
"2015" 3
當filter條件如下:
GET /test_filter/filter_type/_search
{
"query": {
"constant_score": {
"filter": {
"term": {
"field": "2011"
}
}
}
}
}
那么這個Filter的執行流程是:
5.1.1.1 搜索
在倒排索引中查找搜索串,獲取document list,此時根據搜索結果得出,符合條件的document list是id為1,4,5,6的document。
5.1.1.2 構建bitset
ES會為每個filter在倒排索引中搜索得到的結果構建一個bitset。bitset很簡單,就是一個二進制的數組,數組下標對應的是當前index中document的搜索順序(不是任何的排序,就是ES存儲的順序,也是查詢的基礎順序,可以通過一個全搜索獲取index的存儲順序。在現在的案例中,存儲順序為id:5、2、4、6、1、3),如我們的案例中,document總計有6個,假設ES的存儲順序就是5、2、4、6、1、3,那么bitset的下標0~5分別對應id為1~6的document。構建的bitset長度就是6。在bitset中,0代表不符合搜索條件,1代表符合搜索條件,那么我們的搜索結果對應的bitset就是:[1, 0, 1, 1, 1, 0]。ES使用bitset來標記document是否符合搜索條件,也是為了用最簡單的數據結構來描述搜索結果,來節省內存的開銷。
5.1.1.3 遍歷bitset
因為一個搜索中可以有多個filter條件,搜索在ES執行后,filter對應的bitset可能有多個,ES會遍歷每個filter對應的bitset,且從最稀疏的開始遍歷,以達到效率最佳。
最稀疏代表bitset中的1最少,1最少代表這個bitset中符合搜索條件的數據最少,從這個bitset開始遍歷,可以盡可能的一次性過濾掉最多的不符合條件的document。
當所有的bitset遍歷結束后,所有的filter條件過濾完成。得到過濾結果。
Filter 2011 [1,0,1,1,1,0] -> 有4個1,代表有4條數據符合過濾條件
Filter 2012 [1,0,0,0,1,1] -> 有3個1,代表有3條數據符合過濾條件
先從filter2012的bitset開始迭代。因為可以一次性過濾掉3個不符合過濾條件的數據。
5.1.1.4 caching bitset
ES會緩存bitset數據到內存中,如果后續的搜索語法中,有相同的filter條件,那么從緩存中直接使用對應的bitset來過濾數據,效率最優。
ES也不是所有的bitset都緩存,其緩存機制是:最近的256個filter中,如果某個filter執行次數達到一定的數量,則緩存bitset。(一定的數量不是固定的,是有一定邏輯算法的,如:10秒內搜索10次,20秒內搜索30次, 50秒內搜索100次)
ES也有不緩存的bitset:如果數據少於1000則不緩存(index中的ducument少於1000)。如果索引分段數據不足索引整體數據的3%也不緩存。(索引分段在后續課程中詳細講解,現在簡單理解為索引的一部分,簡單理解為一個shard)
因為這個bitset的緩存,所以filter的執行效率是比query高的。
這個時候,搜索結果已經返回。ES在緩存bitset的同時,一般已經返回了搜索結果了。也就是一個並發的操作,搜索完成返回結果和緩存bitset同時執行。
5.1.2 執行特性
當多次filter搜索的時候,中間摻雜了數據的寫入操作,那么緩存在內存中的bitset是否就是錯誤的?ES在filter執行過程中,也有其特性,用於解決上述問題。
5.1.2.1 query和filter的執行順序
一般來說,ES會先執行filter,再執行query,因為filter效率高,能夠過濾掉不符合搜索條件的數據。且query是需要計算相關度分數來排序的,執行效率低,如果先執行query,會導致不符合filter過濾條件的數據也參與了相關度分數計算和排序,效率降低。
5.1.2.2 bitset cache auto_update
如果document的數據修改,或新增、刪除了document,那么緩存的bitset會自動更新,保證緩存bitset的數據有效性。這個自動更新是ES自動操作的,不需要關心。
ES實現bitset cache auto_update就是為了解決緩存數據與存儲數據不一致的問題。
5.1.2.3 bitset cache的應用時機
只要在ES中執行query的時候包含filter過濾條件,ES都會先檢查cache中是否有這個filter的bitset cache,如果有,則直接使用,如果沒有,則搜索過濾index中的document。


免責聲明!

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



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