2011-10-08 98 views
5

我们对Sitecore的6.4和正在使用的共享源代码高级搜索模块,并看到在站点搜索性能有很大降解当Sitecore的重新索引化处理踢和更新的变化到网络数据库。Sitecore的搜索性能时重新索引和定制IndexingProvider

当我们揭开序幕,一个完整的网站发布,索引经理拿起变化和处理历史记录,这反过来又重新索引中的每个已受影响的项目。由于这发生在每个项目中,您可以看到磁盘上的Lucene索引在查看目录时发生了变化(文件的数量随着您的观察而增长和变化)。

如果你试图当发生这种情况的公共网站上搜索时,搜索可以采取noticibly较长时间才能完成;并且在重负荷下它可能需要长达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); 
     } 
     } 
    } 

它触发更新事件,其由DatabaseCrawler,因为它连接到IndexingProvider.OnUpdateItem事件处理;但为什么上面的方法也调用Sitecore.Data.Indexing.Index.UpdateItem方法?我认为6.5版本的命名空间正在被折旧,所以我很惊讶地发现新命名空间和旧命名空间之间的联系。

因此,它看起来像DatabaseCrawler正在处理更新,删除该项目,然后再次将其添加到索引;然后旧的Sitecore.Data.Indexing.Index也会尝试更新它。这里肯定有问题吗?我不知道,所以如果我错了,请纠正我的错误,这正是我在无需任何调试的情况下追踪反编译的代码时的样子。

+0

这似乎是先进的(和漂亮整洁的东西)你想这样做(和迄今所做的)。也许你应该尝试与Sitecore谈论它...如果你有改进,我确定他们喜欢听到他们:) – Holger

+1

嗨蒂姆,我只能想到这一点,当索引要么完全重建每个发布或者你有大量的用户在做搜索。你是否有大量的游客或为重建而特别设置的东西?你可以尝试禁用索引的更新,然后进行相同的测试吗?它可能与一般发布有关,而不仅仅是索引。 –

+0

@Jens,谢谢我们将尝试禁用索引过程。就内容大小或访客数量而言,我觉得我们不会做任何不寻常的事情。该网站相对较小。但是我们需要知道性能会不断扩大。如果索引完全重建,它会更快速地工作,大约5秒钟完成重建。逐个更新每个项目可能会花费更长的时间,因为您会形象化。 –

回答

2

我建议两两件事:

  1. 使用Advanced Database Crawlerv2是最新的版本),它封装在Sitecore.Search命名空间。这使得使用Lucene.NET和Sitecore非常容易。

  2. 每天完全重建索​​引。这会对索引进行碎片整理,因为碎片随着时间的推移会降低性能(这可能是您的问题)。

+0

我试过使用ADC,它会影响你的解决方案。之后,我将其删除。 –

1

我遇到过类似的问题。当我分析时,所有时间都在为每个搜索打开索引。

我们最终解决这个问题的方式是绕过Sitecore的索引类并直接进入Lucene。 Lucene提供了一个“Reopen”方法,它只打开修改后的段文件,而不是像Sitecore那样的所有段文件。

所以,我们所做的是:

  1. 打开索引读者,如果我们没有一个已经
  2. 创建应用程序级别引用它,这样我们就可以重新使用它
  3. 在每个搜索调用应用指数读者“重新打开”
  4. 搜索

看一看的Lucene.Net.Index.IndexReader.Reopen我的ThOD Documentation

您可以从Sitecore.Search.Index.CreateReader索引读卡器()