我们每隔7小时对Lucene索引和增量索引每7天运行一次完整的重新索引(即从头开始创建索引)。我们的索引有大约700,000个文档,完整索引需要大约17个小时(这不是问题)。
当我们执行增量索引时,我们只会对过去两小时内已更改的内容进行索引,因此所需时间会少得多 - 大约半小时。但是,我们注意到很多时候(可能是10分钟)花在运行IndexWriter.optimize()方法上。
LuceneFAQ提及:
IndexWriter类支持optimize()方法,该方法可压缩索引数据库并加快查询速度。在执行文档集的完整索引或索引的增量更新之后,您可能希望使用此方法。如果增量更新经常添加文档,则只需要偶尔执行一次优化,以避免额外的优化开销。
...但这似乎没有给出“经常”含义的任何定义。优化是CPU密集型和非常密集的IO,所以如果我们能够摆脱它,我们宁愿不这样做。在未优化的索引上运行查询的效果是多少(特别是在完全重新索引之后的查询性能方面与20个增量索引之后相比,例如50,000个文档已经更改)?我们应该在每个增量索引之后进行优化还是性能损失不值得呢?
答案 0 :(得分:16)
Mat,因为您似乎很清楚当前流程需要多长时间,所以我建议您删除optimize()
并衡量影响。
这些2小时的窗户中有很多文件发生了变化吗?如果只有一小部分(50,000 / 700,000约为7%)被逐步重新编入索引,那么我认为你没有从optimize()
获得更多价值。
一些想法:
optimize()
。我的经验表明,无论如何你都没有看到巨大的查询改进。optimize()
代替2小时。optimize()
(这是javadoc所说的内容。)并确保您进行测量。这些变化可以在没有它们的情况下在黑暗中拍摄。
答案 1 :(得分:4)
optimize
操作会读取和写入整个索引,这就是IO密集型的原因!
优化操作背后的想法是将Lucene索引中的所有各个段重新组合成一个单独的段,这可以大大减少查询时间,因为您不必每次查询打开和搜索多个文件。如果您使用的是普通的Lucene索引文件结构(而不是组合结构),则每次提交操作都会获得一个新段;和我假设的重新索引一样吗?
我认为Matt有很好的建议,我会说他所说的一切 - 由你拥有的数据驱动。我实际上会更进一步,只在需要时选择a)b)当你的查询量很低时。
由于查询性能与索引中的细分数量密切相关,因此简单的ls -1 index/segments_* | count
可能是实际需要优化时的有用指标。
或者,跟踪查询性能和音量,并在达到令人难以接受的低性能且可接受的低音量时启动优化将是一个更好的解决方案。
答案 2 :(得分:2)
在this mail中,如果您的索引看到不断更新,则Otis Gospodnetic建议使用optimize 。这是从2007年开始,但是调用optimize()
本质上是一个IO重型操作。您可以考虑使用更加逐步的方法;一个MergeScheduler