1 Schema 设计注意事项
1.1 indexed fields
索引字段数量的增加会引起:
索引期间的内存使用(Memory usage during indexing)
段合并时间(Segment merge time)
优化时间(Optimization times)
索引大小(Index size)
可以使用 omitNorms=true 来减少这些影响
1.2 Stored fields
在query时,召回一些存储的字段会产生很大开销。花费的开销主要取决于文档的存储大小 — 存储越大,在磁盘上分布就越稀松,产生的磁盘I/O就越大。(通常是存在大字段的时候,比如存储文档的正文)。
2 Configuration Considerations
2.1 mergeFactor
mergeFactor决定这段(segment)的数量。
mergeFactor的值决定了Lucene在构建多少个相同大小的segment的时候进行合并。
例如,如果mergeFactor设置为10,每新增1000(设置maxBuffredDocs)个文档就会创建一个新的segment。当增加第10个有1000个文档的segment时,当前的10个segment 会合并为1个大小为10000的segment。当添加10个10000的segment时,将会合并成一个100000的segment。以此类推,因此不会出现超过9个segment的时候。
mergeFactor Tradeoff
较高的值(例如25)
优点:可以提高构建索引的速度
缺点:不会频繁段合并,导致会在多个索引文件检索,可能会降低搜索速度。
较低的值(例如2)
优点:减少引文件数量,提高搜索速度。
缺点:频繁进行段合并,会降低构建索引的速度。
2.2 HashDocSet Max Size Considerations
HashDocSet 是在solrconfig.xml。
设定较小的集合,能带来更高的内存、循环、聚合的效率。
HashDocSet的大小主要看文档数量 — 文档数量越大,就设置更大的hashDocSet。可能需要进行多次测试找到最佳的数字。
一般设定为文档总数乘以0.005。
尝试到这个值之间的值,测试一个最佳的查询时间。
当查询趋于稳定,如果较大和较小之间没太大差异,有限使用较大的值。
注意:从版本1.4.0开始,hashDocSet不再是Solr的一部分,SOLR-1169.
2.3 Cache autoWarm Count Considerations
当一个新的搜索器(searcher)被打开时,会从旧的搜索器中的cache热加载方式入驻到新搜搜器的cache里。autowarmCount是配置被复制到新搜索器中的数量。
2.4 Cache hit rate
在solr的admin后台可以监控缓存的统计数据。提高solr的缓存大小通常都可以提高性能,特别是当你发现某个缓存经常被清除的时候。特别需要注意filterCache,一般用于在facet。
2.5 Explicit Warming of Sort Fields
如果你有很多用于排序的字段,在newSearcher和firstSearcher中增加预加载会提升这些字段。因为FieldCache是在用户查询之前就已经填充到缓存中。
3 Optimization Considerations
你可能想优化索引,例如你想构建出一个索引,然后不再修改。
如果索引是快速变化的,你将需要较低的合并策略。优化是非常消耗资源的。
如果索引不断变化的,那么合并带来的性能提成不会持续很长时间。一般不值得在这种费静态的索引上做频繁做段优化。
4 Updates and Commit Frequency Tradeoffs
如果Slaves节点频繁接收到collection更新将会影响性能。为了避免这种情况,你必须了解slave是如何更新cloolection的,才能更好的调整相关参数降低更新频率。(number/frequency of commits, snappullers, and autowarming/autocount)
当client在master节点上执行commit、optimize命令进行commit、optimization操作时,都会生成一个collection的快照。
Slave节点上的Snappullers会定时检查master上的新镜像。如果发现新的镜像版本将下载并执行snapinstall。
当打开一个新的Searcher时,会在查询交接之前,提前对缓存进行热加载。缓存热加载对查询延迟是至关重要的。
三个相关参数:
number/frequency of snapshots,取决于客户端的操作。
snappullers定时器。可以每秒、每天的运行。单只会获取最新的并且没有的collection。
Cache autowarming 在solrconfig.xml中配置所有的cache。
如果你希望频繁产生的新collection能达到“live online”,则你必须频繁的commits/snapshots和 snappulls。保证较好的性能通常设定的时间为1-5分钟。具体取决于对缓存的依赖程度和预热的时间。
缓存预热对性能至关重要。一方面,必须有足够的实体填充到新的缓存中,以便在切换查询时可以从缓存个中进行查询。另一方面,自动预热一个新的collection需要花费很长时间,尤其是它只使用单线程单cpu。如果设置的snapinstaller操作过于频繁,则salve节点将一直在查询旧的collection,一个新的collection正在预热时,另一个新的又被开始预热。
如果我们试图解决这个问题,我们必须先将第一个collection作废后在使用第二个,然后当第三个collection预热,我们必须作废第二个collection,以此类推。一个没有完整热加载完毕的collection无法充分发挥作用。可以通过配置调整这种情况,以免新collection安装的太快。
5 Query Response Compression
某些情况下,我们可以将Solr返回的XML进行压缩。如果返回结果太大,NIC I/O收到限制,并且不是千兆网卡时,则可以使用压缩是一个解决方案。
压缩会增加CPU的使用率,Solr是强依赖CPU的服务,压缩会降低查询性能。压缩可以将文件减少到原来的1/6,网络传输减少到原来的1/3。同时查询性能会降低15%。
6 Indexing Performance
一般情况下,批量更新文档比单个更新速度更快。
对于Java Client(3.x版本)批量更新使用StreamingUpdateSolrServer.java,它使用多线程多连接流式传输。注意在4.x版本,不自在推荐使用StreamingSolrServer,而是推荐使用ConcurrentUpdateSolrServer;对于SolrCloud请使用CloudSolrServer。
减少自动提交的频率或者禁用,可以加快索引的速度。但是这会增加对内存的使用,从而影响性能,主要是过多的内存交换和垃圾回收。
7 RAM Usage Considerations
OutOfMemoryError
如果Solr实例没有分配足够的内存,则JVM有可能会报异常OutOfMemoryError。不会损坏数据,solr会尝试修复。当时正在进行的添加/删除/提交不会成功。也会产生其他的影响,例如使用SimpleFSLock锁机制(1.2版本),OutOfMemoryError会导致Solr失去多index的锁,此时尝试去修改所以会报错SEVERE: Exception during commit/optimize:java.io.IOException: Lock obtain timed out: SimpleFSLock@/tmp/lucene-5d12dd782520964674beb001c4877b36-write.lock
如果想在OOM的时候看到堆栈信息请添加设置"-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/to/the/dump"
Memory allocated to the Java VM
解决此错误最简单的方法是,在屋里内存尚未全被使用时,给Solr运行的JVM增加内存。使用Sun虚拟机可以增加参数-Xms and -Xmx ,例如:java -Xms512M -Xmx1024M -jar start.jar
想要了解不同JVM的内存池区别可以使用jconsole、visualvm、SPMSolr性能监控(https://sematext.com/spm/),进行长时间监控。
Factors affecting memory usage
你可能希望减少Solr对内存测使用。
文档的大小:
在处理添加文档命令是,XML更新有2个限制:
文档的所有字段必须同时存在内存中,也就是min(实际长度,maxFieldLength)的总和,所以调整maxFieldLength是有用的。
所有field都能在内存中,此时不管maxFieldLength。
注意:不同的add命令运行在不同的线程中。线程越多,内存使用量就越大。
在索引过程中,内存使用率会随着dockments的增加而增加,直到执行commit命令为止。提交(包括软提交)将释放几乎所有的堆内存。索引过程中,为了避免大堆的垃圾回收产生的暂停,请定期执行软提交。或者在solrconfig.xml启动autoCommit(或autoSoftCommit)