在Lucene中使用增量索引之后是否应该优化索引?

时间:2020-03-06 14:35:19  来源:igfitidea点击:

我们每7天对Lucene索引运行一次完整的重新索引(即从头开始创建索引),每2个小时左右运行一次增量索引。我们的索引大约有700,000个文档,一个完整的索引大约需要17个小时(这不是问题)。

当我们进行增量索引时,我们仅索引过去两个小时内发生变化的内容,因此花费的时间要少得多,大约半小时。但是,我们已经注意到,这段时间中的很多时间(可能是10分钟)都花在了运行IndexWriter.optimize()方法上。

LuceneFAQ提到:

The IndexWriter class supports an optimize() method that compacts the index database and speeds up queries. You may want to use this method after performing a complete indexing of your document set or after incremental updates of the index. If your incremental update adds documents frequently, you want to perform the optimization only once in a while to avoid the extra overhead of the optimization.

...但是,这似乎并未对"频繁"的含义给出任何定义。优化需要占用大量CPU和IO,因此,如果我们可以避免的话,我们宁愿不要这样做。在未优化的索引上运行查询会带来多少损失(我在考虑完全重新索引后的查询性能,而不是20个增量索引(其中50,000个文档已更改)后的查询性能)?我们应该在每个增量索引之后进行优化,还是对性能造成的损失是不值得的?

解决方案

Mat,由于我们似乎对当前的过程需要花费多长时间有所了解,因此建议我们删除" optimize()"并评估其影响。

在那两个小时的窗口中,许多文档会更改吗?如果仅一小部分(50,000 / 700,000大约为7%)被重新索引,那么我认为我们不会从optimize()中获得太多价值。

一些想法:

  • 根本不要执行增量的" optimize()"。根据我的经验,无论如何我们都不会看到巨大的查询改进。
  • 每天而不是每2小时执行一次optimize()。
  • 在小批量时间内执行" optimize()"(这是javadoc所说的)。

并确保我们进行测量。没有它们,这些变化可能是黑暗中的一击。

"优化"操作读取和写入整个索引,这就是为什么它需要大量IO的原因!

优化操作背后的想法是将Lucene索引中的所有各个段重新组合为一个段,这可以大大减少查询时间,因为我们不必每次查询都打开和搜索多个文件。如果我们使用的是普通的Lucene索引文件结构(而不​​是组合结构),则每次提交操作都会获得一个新的段。与我假设的重新索引相同?

我认为Matt有很好的建议,而我会说第二点他所说的一切都是由我们拥有的数据决定的。实际上,我将更进一步,仅在需要时优化a),在查询量较低时优化b)。

由于查询性能与索引中的段数密切相关,因此可以使用简单的`ls -1 index / segments_ * |。 count可能是确定何时需要优化的有用指标。

另外,跟踪查询性能和数量并在达到可接受的低数量时达到不可接受的低性能时启动优化将是一个更好的解决方案。

如果索引不断更新,在此邮件中,Otis Gospodnetic建议不要使用优化。它是从2007年开始的,但是调用optimize()本质上是IO繁重的操作。我们可以考虑使用更逐步的方法。合并调度程序