solr查詢優化(實踐了一下效果比較明顯)


什么是filtercache?

    solr應用中為了提高查詢速度有可以利用幾種cache來優化查詢速度,分別是fieldValueCache,queryResultCache,documentCache,filtercache,在日常使用中最為立竿見影,最有效的應屬filtercache,何謂filtercache?這個需要從一段solr的查詢日志開始說起,下面是我截取的solr運行中打印的一段查詢日志:

[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=5,queryTime_is ==> 2                                      
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A1+AND+class_id%3A1+AND+%28group_id%3A411%29&sort=gmt_create+desc&start=0&rows=20,queryTime_is ==> 2                  
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=5,queryTime_is ==> 2                                      
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A1+AND+class_id%3A1+AND+%28group_id%3A8059%29&sort=gmt_create+desc&start=0&rows=20,queryTime_is ==> 0                 
[search4alive-0] Request_is ==> debugQuery=on&group=true&group.field=group_id&group.ngroups=true&group.sort=gmt_create+desc&q=status%3A0++AND+biz_type%3A1+AND+class_id%3A1+AND+ha
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=30&rows=30,queryTime_is ==> 4                                    
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=5,queryTime_is ==> 1                                      
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A1+AND+class_id%3A1+AND+%28group_id%3A375%29&sort=gmt_create+desc&start=0&rows=20,queryTime_is ==> 3                  
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=5,queryTime_is ==> 1                                      
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=30,queryTime_is ==> 4                                     
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=5,queryTime_is ==> 1                                      
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=30,queryTime_is ==> 4                                     
[search4alive-0] Request_is ==> q=status%3A0++AND+biz_type%3A2+AND+class_id%3A1&sort=index_sort_order+desc&start=0&rows=30,queryTime_is ==> 3                                     

   看到這段查詢日志之后,我們開始考慮如何提升查詢的rt(查詢速度),因為在參數q中的查詢是要有磁盤IO開銷的,很自然的思路是將整個查詢的參數q作為key,對應的結果作為value,這樣做是可以的,但是查詢的命中率會很低,會占用大量內存空間。

   查詢參數q上基本上每次都會出現status,biz_type,class_id 對於這樣的字查詢,所以可以把整個查詢條件分成兩部分一部分是以status,biz_type,class_id 這幾個條件組成的子查詢條件,另外一部分是除這三個條件之外的子查詢。在進程查詢的時候,先將status,biz_type,class_id 條件組成的條件作為key,對應的結果作為value進行緩存,然后再和另外一部分查詢的結果進行求交運算。

 

  

       通過上面這幅圖明白了filtercache的意義是,將原先一個普通查詢分割成兩個組合查詢的與運算,兩個子查詢至少有一個使用緩存,這樣既減少了查詢過程的IO操作,又控制了緩存的容量不會消耗過多的內存。

如何使用?

首先要配置solrconfig.xml 要開啟fltercache:

 

Xml代碼   收藏代碼
  1. <query>  
  2.         <filterCache    class="solr.LRUCache"     size="50000"      initialSize="512"      autowarmCount="0"/>  
  3. </query>  

 這里使用的是solr實現的基於LRU算法的緩實現,以上配置是使用solr.LRUCache ,使用這個cache在插入多,查詢少的情況比較使用,如果是查詢多,插入少的情況,可以使用solr.FastLRUCache緩存模塊。

 

 

客戶端API調用:

下面是原先的客戶端端查詢代碼:

 

Java代碼   收藏代碼
  1. SolrQuery query = new SolrQuery();  
  2.   
  3. query.setQuery("status:0 AND biz_type:1 AND class_id:1 AND xxx:123");  
  4.   
  5. QueryResponse response = qyeryServer.query(query);  

 

 

使用filterQuery之后的查詢代碼:

 

Java代碼   收藏代碼
  1. SolrQuery query = new SolrQuery();  
  2.   
  3. query.addFilterQuery("status:0 AND biz_type:1 AND class_id:1");  
  4. query.setQuery("xxx:123");  
  5.   
  6. QueryResponse response = qyeryServer.query(query);  

 

經過測試這樣優化之后,查詢的RT(查詢速度)會明顯減小,QPS(每秒查詢率)會有明顯提升。

 

使用filterquery過程中需要注意點:

 

●不能在filterQuery 上重復出現query中的查詢參數,如果上面的filterquery調用方法如下所示:

 

Java代碼   收藏代碼
  1. query.addFilterQuery("status:0 AND biz_type:1 AND class_id:1 AND xxx:123");  
  2. query.setQuery("xxx:123");  

 如上,條件xxx:123 在filterQuery和query上都出現了,這樣的寫法非但起不到查詢優化的目的,而且還會增加查詢的性能開銷。

 

●盡量減少調用addFilterQuery方法的次數

Java代碼   收藏代碼
  1. query.addFilterQuery("status:0 ");  
  2. query.addFilterQuery("biz_type:1 ");  
  3. query.addFilterQuery("class_id:1 ");  
  4. query.setQuery("xxx:123");  

如上,將status:0 AND biz_type:1 AND class_id:1 這個組合查詢條件,分三次調用filterQuery方法來完成,這樣的調用方法雖然是正確的,並且能起到性能優化的效果,優化性能沒有調用一次addFilterQuery方法來得高,原因是多調用了兩次addFilterQuery,就意味着最后需要多進行兩次結果集的求交運算,雖然結果集求交運算速度很快,但畢竟是有性能損耗的。

 

不過從內存開銷的角度來說,調用三次addfilterQuery方法這樣可以有效降低內存的使用量,這個是肯定的。所以在是否調用多次addFilterQuery方法的原則是,在內存開銷允許的前提下,將量將所有filterQuery條件,通過調用有限次數的addFilterQuery方法來完成。

 

下文摘自solr中國

 

What it is used for?

先從內部機制開始。FilterCache存儲了一些無序的文檔標識號(ID)。這些ID並不是我們在schema.xml里配置的unique key,而是solr內部的一個文檔標識。請記住這個。

FilterCache的任務是保持與用戶過濾的結果關聯。另外,cache可以輔助facet機制(在使用TermEnum時),在solrconfig.xml中的<useFilterForSortedQuery/>參數設為true時,還可以進行排序。

Definition
FilterCache的標准定義如下:

Xml代碼
  1. <filterCache
  2.     class=”solr.FastLRUCache”
  3.     size=”16384″
  4.     initialSize=”4096″
  5.     autowarmCount=”4096″ />

有以下的配置可供選擇:
class:實現類。建議使用solr.FastLRUCache,它能在大量的GET、PUT操作下,提供更好的性能。
size:cache的最大值。
initialSize:cache的初始化值。
autowarmCount:從舊的cache到新的cache時,需要被復制的數量。
minSize:在full restoraton的情況下,將cache減小后的值
acceptableSize:如果minSize沒有設置,則該值會替代之
cleanupThread:默認false,如果設為true則會使用一個分離的topic來清理cache。

大部分情況下,設置initialSize和autowarmCount就已經足夠了。

How to configure?
cache的大小,需要根據基本的查詢語句而定;maximum大小應該至少等於我們使用的過濾字段的大小。舉個例子說明:如果在某個時間內,你的應用程序使用了2000個查詢參數,則minimum的大小應該最小設為2000。

Efficient use
然而,光有配置是不夠的,我們還需要讓查詢能夠使用它。請看下面的例子:

 
  1. q=name:solr+AND+category:ksiazka+AND+section:ksiazki

初看起來,查詢語句是正確的。但是有個問題:它並沒有用到filterCache。所有的請求將會綁定到queryResultCache中並創建一個單獨的條目。我們來作一下修改:

 
  1. q=name:solr&fq=category:ksiazka&fq=section:ksiazki
  2. 對應java代碼:
  3.     SolrQuery query = new SolrQuery(); 
    1.  
      query.addFilterQuery( "category:ksiazka");
    2.  
      query.addFilterQuery( "section:ksiazki");
    3.  
      query.setQuery( "name:solr");
    4.  
       
    5.  
      QueryResponse response = qyeryServer.query(query);
     

有什么變化呢?在這個例子中,一個條目會寫入到queryResultCache中;另外,還會有兩個條目會寫入到filterCache中。現在看一下下面的語句:

 
  1. q=name:lucene&fq=category:ksiazka&fq=section:ksiazki

這個查詢會創建一個條目到queryResultCache中,但是會使用filterCache中兩個已經存在的條目。這樣查詢的執行時間會降低,IO的使用也會節省。

然而,對於下面的查詢:

 
  1. q=name:lucene+AND+category:ksiazka+AND+section:ksiazki

solr不能使用任何cache並且需要從lucene索引中收集所有的信息。

Last few words
就像你所看到的,配置cache 的正確方法不是如何保證solr能夠使用它,而是如何構建查詢語句來提升性能。當考慮查詢的時候,請考慮這一點。


免責聲明!

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



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