古道长亭

Contact me with ixiaoqiang0011@gmail.com


  • 首页

  • 归档

  • 分类

  • 关于

  • Book

  • 搜索

Solr性能优化

时间: 2023-06-27   |   分类: Solr   搜索引擎   | 字数: 3791 字 | 阅读约: 8分钟 | 阅读次数:

Solr性能优化

1. 配置文件

1.1 schema.xml配置

schema 配置不合理,往往会导致查询性能低,索引占用磁盘、内存空间大的问题

  • 合理设置域属性
    • 域是否要检索(indexed),是否要存储(stored),按需配置,避免不必要的空间浪费。
    • 域是否需要根据文本长度算分,是否需要在建索引时设置权重,如果不需要,设置omitNorms=true
    • omitPositions、omitTermFreqAndPositions,词频信息和打分相关,位置信息和高亮显示相关,当不需要这些功能,则可设置为 true,节省磁盘空间,提升搜索速度。
    • 对于需要排序的字段,使用 docValues,构造 fifieldCache 会进行压缩,节省内存使用
  • 使用正确的数据类型
    • 对于数值类型,使用能正确存储的最小数值类型,更小的数值类型占用更小的磁盘、内存、CPU缓存,并且处理时的 CPU 周期也更少。
    • 数值类型不要用 string,一个整型占 4 字节,用 string,大小为 1000 以上的整型就占了 4 个字节了。当然,对于只有几个值(比如 0、1、2、3)的可枚举的,可以用 string。
    • 不需要分词的域,用 string,不要用 text,text 默认用标准分词器分词。
    • 需要范围查询的数值类型,需要使用 plong、pint 等分精度索引的类型,范围查询性能是不分精度索引的数值类型的 10 倍。当然,也不能滥用,分精度索引的数值类型比较占用空间,如果没有范围查询的需求,则不需要使用。

1.2 solrconfig.xml

  • 索引目录类型

    • 采用 NRTCachingDirectoryFactory,这种目录类型,小索引会缓存在内存中,减少磁盘 IO。而且这些小文件往往是频繁变化的,放在内存中,则 reopen 的时候,不需要读磁盘,性能会好很多。

    • autoSoftCommit 和 autoCommit

      hardcommit 作用是使索引持久化,会 flflush 当前正在索引的段到磁盘,比较重,影响查询性能,时间间隔可以设置得较长。没有 hardcommit,机器挂了 ,重启后,会从 tlog 恢复。

      softcommit作用是使索引可见,可根据实时性需要设置适当的长度。需要注意,softcommit会导致searcher层cache失效。索引实时性要求不高的情况下,频率尽可能设置长一点

  • cache配置

    • 缓存类型

      1.queryResultCache,查询结果缓存,key 由 q 参数、fq 参数、sort 参数组成,value 是 docId 和
      score(score 可能没有)的有序集合 DocList。只要 q、fq、sort 参数有一个变化了,则属于不同
      的 key,不会命中结果。
      2.documentCache,document 的缓存,key 是 docId,value 是 document。
      3.filterCache,filterQuery 结果缓存,key 是 fq 参数的值,value 是 docId 的无序集合 DocSet。
      4.fieldCache,正排索引缓存,可通过 docId 获取字段值。排序、facet、group 等需要正排索引的
      查询需要用到 fieldCache。fieldCache 是基于段的,一个字段的 fieldCache 是在第一次使用的时
      候加载到内存中的。Lucene 用一个 weakHashMap 存放已加载的段的 fieldCache,key 为段的
      indexReader。因此,fieldCache 是常驻内存,不会自动释放的,除非段被合并,不存在了,才会
      释放掉。使用时,要注意内存的消耗,避免内存不够用,发生 OOM。
      
    • 缓存注意事项

      1.queryResultCache、documentCache、filterCache 都是 searcher 级别的缓存,searcher 重新
      打开(softcommit 会触发),则缓存失效。其中 queryResultCache、filterCache 可以配置
      autowarm 使 searcher 预热时重新加载。documentCache 的 key 是 docId,重新打开后,
      document 的 id 已经变化,因此 documentCache 不能进行 autowarm。
      <filterCache class="solr.LRUCache" size="16384" initialSize="4096" autowarmCount="4096"/>
      2.对于实时查询(比如 softcommit 频率为 1 秒),最好不要配置 cache,因为缓存失效太快,缓存
      命中率可能比较低,如果配置了 autowarm,还会导致不停的 autowarm,加重服务器负担。除
      非查询语句都比较集中,缓存条目很少。
      3.对于有翻页的查询,可以适当调整 queryResultWindowSize 参数,比如一页的大小为 10,则
      queryResultWindowSize 设置为 50,则后面 4 页,都会命中缓存,当然参数设置越大占用内存越
      多
      4.enableLazyFieldLoading 配置为 true,只读取需要的字段。这个属性要配合 documentCache 使
      用,即开启了 documentCache,才能发挥 lazyLoading 的作用。
      举个例子,比如查询出来的条目可能只显示简单的信息,点击具体条目,则需要把整个条目的所有信 息展示出来。则点击具体条目去查询时,命中了 cache,获取到的 document 就是有 lazyField 的 document 了,Solr 把它返回给调用者时,就会去加载 lazyField 的真实的值。
      5.可配置 firstSearcher、newSearcher 来预热耗时的查询,使查询结果缓存起来,使查询性能更平
      滑。
      <listener event="newSearcher" class="solr.MyQuerySenderListener">
      

2. 索引构建

建议采用离线方式构建索引 ,离线构建索引的好处:

  • 避免在线构建索引对在线服务的影响。
  • 不用考虑记录更新的情况,省掉查询老记录是否存在的步骤,性能有提升。
  • 可以使用内存大的机器,在内存中(RAMDirectory)进行构建(内存放不下,可考虑一个段一个段的构建),速度往往是在线构建的好几倍。
  • 离线构建可以打开多个 indexWriter 进行构建(最好多个进程,因为 IndexWriter 存在类上加锁的情况,多个线程还是存在锁等待),然后再合并到一个 index 里,虽然在线索引也可以多个线程并发写,但会存在并发锁的问题。
  • 离线索引追求的是吞吐量,对响应时间要求不高,可按照高吞吐量调配 jvm 参数,而在线索引还得考虑 jvm 对在线查询的影响。
  • 离线构建可减少中间的段的生成,可以调大 ramBufffferSzie 和 mergeFactor,避免生成小的段,避免在构建的过程中自动合并,在构建完成后再根据需要触发合并动作,省掉中间的合并过程,速度也有一定的提高。

3. 搜索

  • 如果不是所有字段都需要返回,则明确指定需要返回的字段,减少系统开销

  • 一次返回的记录数不要太多,深度翻页使用 cursorMark 参数提升性能

    //查询优化:游标查询
        public void cursorQuery() throws Exception {
            //solr查询封装
            SolrQuery sq = new SolrQuery();
            sq.setRows(2);//设置游标一次读的数量
            sq.set("q", "*:*");//按条件检索
            sq.setSort("id", SolrQuery.ORDER.asc);//根据主键排序
            String cursorMark = CursorMarkParams.CURSOR_MARK_START;//游标初始化
            boolean done = false;
            while (!done) {
                sq.set(CursorMarkParams.CURSOR_MARK_PARAM, cursorMark);//变化游标条件
                QueryResponse rsp = solrClient.query(sq);//执行多次查询读取
                String nextCursorMark = rsp.getNextCursorMark();//获取下次游标
                // 做一些操作数据的事
                for (SolrDocument sd : rsp.getResults()) {
                    System.out.println(sd.get("id"));
                }
                //如果两次游标一样,说明数据拉取完毕,可以结束循环了
                if (cursorMark.equals(nextCursorMark)) {
                    done = true;
                }
                cursorMark = nextCursorMark;
            }
        }
    
  • 查询条件中包含路由字段的,可以先计算出分片,再从分片中获取机器,并指定 shard 来查询,只查询相应的 shard,避免服务端所有 shard 都查询

    String shards = "192.168.1.215:8983/solr/a,192.168.1.214:8983/solr/b"; solrParams.set("shards", shards);//设置shard
    
  • 合理使用 filterquery,filterquery 结合 filterCache,能把常用的查询条件缓存起来,提升查询效率。对于不使用 filterCache 的情况下,多个 OR 条件组合起来的查询也应该用 filterquery,因为filterquery 是不算分的,性能会好很多。主查询中的 OR 查询,对于一个 document 并不是有一个 OR 查询条件命中即返回,接着去查下一个 document,而是所有的 OR 条件都去查一遍,记录命中的 OR 条件的数量,由此来计算得分,所以会比在 filterQuery 中查询慢很多

4. 系统

  • 内存分配

    合理设置 jvm 内存大小,Solr 缓存、lucene 缓存、词典文件等都需要加载到内存中,内存设置太小,会造成 gc 频繁。但也不要把内存用得太满,在 jvm 内存足够的情况下,多留点给操作系统做文件缓存,这样索引文件能更多地被操作系统缓存起来,减少磁盘 IO,提升搜索的性能

    方法一:直接修改配置文件参数 
    打开solr\bin目录下的solr.in.sh脚本文件 
    搜索找到 SOLR_HEAP 或者 SOLR_JAVA_MEM ,然后修改 
    SOLR_HEAP="1024m" 或者 
    SOLR_JAVA_MEM="-Xms512m -Xmx512m" 
    
    方法二:修改JVM内存存执 
    打开 tomcat\bin下面的catalina.sh文件,加入 
    set JAVA_OPTS= -Xms1024m -Xmx1024m 
    
    方法三:修改系统环境变量 
    设置CATALINA_OPTS 或者 JAVA_OPTS 
    CATALINA_OPTS="-Xms128m -Xmx1024m -XX:PermSize=64M -XX:MaxPermSize=512M " 
    
    方法四:在启动时直接设置JVM大小 
    ./solr -m 2g
    
  • swap

    系统内存不足时,操作系统会拿交换区(磁盘)来当做内存使用,交换区的访问速度和内存比非常慢,会影响搜索的性能,对 gc 也有较大的影响,jvm 收集交换区的垃圾对象时,常常速度很慢,造成应用停顿。建议内存足够的情况下,把 swap 关掉。如果内存比较紧张,则建议把 swapness参数的值调小,让操作系统尽量少使用 swap,完全关掉可能会造成操作系统内存不足,进程而被操作系统 kill 掉

    如果内存够大,应当告诉linux不必太多的使用SWAP分区,可以通过修改swappiness的数值。swappiness=0的时候表示最大限度使用物理内存,然后才是swap空间,swappiness=100的时候表示积极的使用swap分区,并且把内存上的数据及时的搬运到swap空间里面。
    现在一般1个G的内存可修改为10,2个G的可改为5,甚至是0。具体这样做:
    1.查看你的系统里面的swappiness
    	$cat/proc/sys/vm/swappiness
    2.修改swappiness值为10
    	$sudo sysctl vm.swappiness=10
    但是这只是临时性的修改,在你重启系统后会恢复默认的,为长治久安,还要更进一步:	
    	$sudo gedit /etc/sysctl.conf
    在这个文档的最后加上这样一行:
    	vm.swappiness=10	
    
  • 磁盘

    搜索引擎对磁盘的随机访问比较多,推荐使用 ssd 磁盘

#Solr# #搜索引擎#
QQ扫一扫交流

标题:Solr性能优化

作者:古道长亭

声明: 欢迎加群交流!

如有帮助,欢迎多多交流 ^_^

微信打赏

支付宝打赏

SolrCloud
Solr数据操作
  • 文章目录
  • 站点概览
古道长亭

古道长亭

Always remember that your present situation is not your final destination. The best is yet to come.

226 日志
57 分类
104 标签
GitHub Gitee
友情链接
  • 古道长亭的BOOK
  • JAVA学习
标签云
  • Mysql
  • 搜索引擎
  • Mybatis
  • 容器
  • 架构
  • 消息队列
  • Flink
  • Sharding sphere
  • 流处理
  • 缓存
  • 1. 配置文件
    • 1.1 schema.xml配置
    • 1.2 solrconfig.xml
  • 2. 索引构建
  • 3. 搜索
  • 4. 系统
© 2019 - 2024 京ICP备19012088号-1
0%