我们使用Sitecore 6.4并且正在使用共享源高级搜索模块,并且当Sitecore重新索引过程启动并更新对Web数据库的更改时,网站搜索性能会大幅下降。
当我们启动完整站点发布时,索引管理器会获取更改并处理历史记录,而历史记录又会重新索引受影响的每个项目。当每个项目发生这种情况时,您可以看到磁盘更改时的Lucene索引,同时查看目录(文件数量增长并在您观看时更改)。
如果您在发生这种情况时尝试在公共网站上进行搜索,则搜索可能需要花费更长的时间才能完成;在重载下,重新索引过程完成之前可能需要15秒的时间。
我可以看到这个过程由IndexingProvider类控制。有没有办法覆盖这个类并实现我们自己的?
我们查看了搜索逻辑,可以看到每次请求搜索时都会创建一个IndexSearchContext对象,从而创建一个新的IndexSearcher。我们更改了一些逻辑,以便将IndexSearchContext保存为单元,这当然意味着同一个Lucene IndexSearcher可以提供多个请求。这大大减少了内存消耗,因为建议使用相同的搜索器来提高性能。
但是,在执行此操作时,在创建新的IndexSearcher之前,不会获取对索引的更改。我们需要一种方法来通知我们的代码索引过程已经完成,然后我们可以重置我们的单例IndexSearchContext对象。我们如何将此逻辑集成到Sitecore配置的代码中?
手动重建索引时,只需约5秒钟即可完成。显然,这有效地删除了索引,然后再次创建它,但为什么逐项更新需要这么长时间?是否有更好的方法可以在不逐项的情况下实现更新过程,而且不会影响公共网站?
我本以为其他人会受到这个问题的影响,所以我很想知道人们是如何解决这个问题的。
编辑 - 来自Sitecore论坛的其他信息
Sitecore.Search代码似乎大量使用为单个操作创建/部署新的Lucene对象。对于大型环境来说,它似乎不太可扩展,这就是我看到代码时感到惊讶的原因。特别是如果索引很大并且每天都有很多内容更新/发布。
通过dotPeek查看类我无法看到我们如何覆盖IndexUpdateContext,因为它是在非虚方法中创建的。自定义DatabaseCrawler可以获得一些访问权限,但只能访问已创建的上下文对象。
我注意到我们可以在web.config中为每个索引定义我们自己的索引实现。我们还可以重新实现爬虫(我们已经从共享模块中使用了高级爬虫),并且可以控制索引过程。我不愿意将太多的Sitecore代码提取到我们自己的实现中,因为它可能会影响未来的更新。
我对IndexingProvider有一个问题。在以下方法中:
private void UpdateItem(HistoryEntry entry, Database database)
{
int count = database.Indexes.Count;
if (count != 0 || this.OnUpdateItem != null)
{
Item obj = database.GetItem(entry.ItemId, entry.ItemLanguage, entry.ItemVersion);
if (obj != null)
{
if (this.OnUpdateItem != null)
this.OnUpdateItem((object) this, (EventArgs) new SitecoreEventArgs("index:updateitem", new object[2]
{
(object) database,
(object) obj
}, new EventResult()));
for (int index = 0; index < count; ++index)
database.Indexes[index].UpdateItem(obj);
}
}
}
它会触发update事件,该事件由DatabaseCrawler处理,因为它附加到IndexingProvider.OnUpdateItem事件;但为什么上面的方法也调用Sitecore.Data.Indexing.Index.UpdateItem方法?我认为该命名空间在6.5版本中被折旧,所以我很惊讶地看到新命名空间和旧命名空间之间的链接。
所以看起来DatabaseCrawler正在处理更新,删除项目然后再将它添加到索引中;然后旧的Sitecore.Data.Indexing.Index也尝试更新它。当然这里有问题吗?我不知道,如果我错了请纠正我,这就是我在没有任何调试的情况下跟踪反编译代码时的样子。
答案 0 :(得分:2)
我会推荐两件事:
使用包含Sitecore.Search
命名空间的Advanced Database Crawler(v2是最新版本)。这使得Lucene.NET与Sitecore一起使用变得非常容易。
每天完全重建索引。这会对索引进行碎片整理,因为随着时间的推移碎片会降低性能(这可能是您的问题)。
答案 1 :(得分:1)
我之前遇到过类似的问题。当我被分析时,所有的时间都花在为每次搜索打开索引上。
我们最终解决问题的方法是绕过Sitecore的索引类并直接转向Lucene。 Lucene提供了一种“重新打开”方法,该方法仅打开修改后的段文件,而不是像Sitecore那样的所有段文件。
所以我们做的是:
查看Lucene.Net.Index.IndexReader.Reopen方法Documentation
您可以从Sitecore.Search.Index.CreateReader()
创建索引阅读器