16

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

当我们做增量索引时,我们只索引在过去两个小时内发生变化的内容,所以它花费的时间要少得多——大约半小时。但是,我们注意到其中很多时间(可能是 10 分钟)都花在了运行 IndexWriter.optimize() 方法上。

LuceneFAQ提到

IndexWriter 类支持压缩索引数据库并加快查询速度的 optimize() 方法。您可能希望在对文档集执行完整索引之后或在索引的增量更新之后使用此方法。如果您的增量更新频繁添加文档,您希望只偶尔执行一次优化以避免优化的额外开销。

...但这似乎没有对“经常”的含义给出任何定义。优化是 CPU 密集型和 IO 密集型的,所以如果我们可以侥幸逃脱,我们宁愿不这样做。在未优化的索引上运行查询的影响有多大(我在考虑特别是在完全重新索引后的查询性能方面,与在 20 个增量索引后相比,例如,50,000 个文档已更改)?我们应该在每个增量索引之后进行优化,还是性能损失不值得?

4

3 回答 3

17

Mat,由于您似乎很清楚当前过程需要多长时间,因此我建议您删除optimize()并衡量影响。

在这 2 小时的窗口中,许多文件是否发生了变化?如果只有一小部分(50,000/700,000 约为 7%)被增量重新索引,那么我认为您不会从optimize().

一些想法:

  • 根本不做增量optimize()。我的经验表明,无论如何您都没有看到巨大的查询改进。
  • 每天做一次,optimize()而不是每两个小时做一次。
  • optimize()在低容量时间执行此操作(这是javadoc所说的)。

并确保您进行测量。没有它们,这些变化可能是在黑暗中拍摄的。

于 2008-09-23T11:16:40.450 回答
4

一个optimize操作读取和写入整个索引,这就是为什么它如此 IO 密集的原因!

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

我认为马特有很好的建议,我会支持他所说的一切——由你拥有的数据驱动。实际上,我会更进一步,仅在需要时优化 a) 和 b) 在查询量较低时优化。

由于查询性能与索引中的段数密切相关,因此ls -1 index/segments_* | count在真正需要优化时,一个简单的指标可能是一个有用的指标。

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

于 2008-12-24T00:57:21.607 回答
2

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

于 2010-10-06T07:59:10.550 回答