zoukankan      html  css  js  c++  java
  • 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();  
          
          query.addFilterQuery("category:ksiazka");
          query.addFilterQuery("section:ksiazki");  
          query.setQuery("name:solr");  
            
          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能够使用它,而是如何构建查询语句来提升性能。当考虑查询的时候,请考虑这一点。


  • 相关阅读:
    好用的绘图工具推荐-processon
    前台获取到的后台json对象取值时undefined的解决方法
    axios怎么引用?
    postman发送post请求,后端无法接收到参数
    bcrypt加密算法
    mongoose创建model名字时,为什么集合名会自动加s?
    《遇见未知的自己》 张德芬
    《把时间当做朋友》笔记摘要
    精英与普通人的区别
    金刚经全文
  • 原文地址:https://www.cnblogs.com/kuyuyingzi/p/4266327.html
Copyright © 2011-2022 走看看