Optimize就是优化的意思。说到Optimize,其实问题回归到两个本质问题:updata-in-place/update-out-of-place、restart。
1 When Optimize
索引update、deleted、add、update、deleted、add反反复复,导致索引“千仓百孔”、“指针琳琳散散”、“无用数据或者辅助数据增多”,最后影响相同的查询逻辑,越到后面检索性能逐渐糟糕。
2 How Optimize
整体optimize、局部optimize、混合optimize
整体optimize,就是对已经存在的索引,整体optimize下,本质就是基于原来索引进行索引重建。这个过程减少了文本IO、文本分析等开销。据经验对于一个个文本文件从磁盘建索引:建完后优化大约=1:0.6.也即基于索引构建索引二次构建时间开销大概是原来从文本构建的0.6. 这个数据规模5000w。超过5000w的可能优化比一定比原始重建省时,反而时间更长。 Lucene/solr 直接由现成的接口indexWriter.optimize(),调用下就可以了。
在最新的3.4 以后,不建议使用optimize,因为这个太耗时了。所以,在接下来的优化中,会逐步优化增量机制,平衡性能和索引规模下时间开销的。
句部optimize,就是对数据先分区(多个子应用),分区下再分组(多个hash分布),二级分组。这样可以对分区内优化、分组内优化、二级组内优化。这样通过降低规模来实现性能和时间平衡。Lucene2.9.1、solr1.4以及以后版本,支持mergePolicy插件化,这样继承默认的policy,然后IndexWriter中set新的policy,就可以针对segment或多目录索引进行局部optimize。
混合optimize,就是整体和局部都执行。这种情况下,整体的频率降低,局部的频率较高。从而实现阶段性的性能最佳。例如一个月一次整体optimize,每天局部optimize,这样可以保证在性能快要出现下滑时,及时restart到最佳性能点。
3 what optimize
索引optimize本质就是索引重建。如何最大程度大块大块利用之前的索引,将大大改进optimize性能。对应lucene默认的optimize来说,文本读取IO、文本分析时间将免去或者这部分开销大大降低。optimize另外一个本质就是restart。optimize就是业务逻辑的回归,有点类似垃圾回收后,内存有空间连续块。optimize之后,指针、存储变得更加紧蹙、高效。在lucene中mergePolicy决定对那些segment合并,或者满足什么属于的segment合并。而合并算法的本质是基于堆排序重新renew 索引。
Lucene/solr默认调参无法满足需求时,开始扩展mergePolicy,此时仍然无法满足需求,需要扣memory了。
抠memory:(1) 对象复用。对大批量、单一流向的操作来说,重用对象将大大降低堆内存消耗,减少ygc。lucene/solr3.4以及以后版本,已经重用document、field对象,批量操作性能更好。
(2)重用 待优化索引的大块对象或者大块数据,从而降低重复计算开销。这块的优化涉及lucene 合并算法。
重度复用的话,需要定做一些数据结构,例如,postlist的块独立化。这方面可以参考“wangsou”,详情不变透露!
(3)调整基础cache大小,做到与os pagecache同步或者改变os pagecache策略。这个问题属于定制index下的os,除了google、baidu、sousou、sogou等大牛已经执行了,其他公司由于业务特性,都很少去优化os这一层。
4 notice
(1)第一次文本建索引属于IO、CPU密集性应用,Optimize上IO密度降低、CPU密度提升。Optimize过程中IO次数尽管少了,memory消耗增多,但是关联的文件数据大小更大。需要平衡大文件颠簸Memory和DISK开销。
(2)Mutithread 多路归并,需要较好的硬件支持。
(3)尽量不要动用optimize,从业务上着手优化性能