Производительность поиска Sitecore при переиндексации и пользовательском IndexingProvider

Мы находимся на Sitecore 6.4 и используем модуль расширенного поиска с общим источником и наблюдаем большое снижение производительности поиска по сайту, когда процесс повторного индексирования Sitecore запускается и обновляет изменения в веб-базе данных.

Когда мы начинаем полную публикацию сайта, менеджер индексирования подхватывает изменения и обрабатывает записи истории, которые, в свою очередь, переиндексируют каждый элемент, который был затронут. Поскольку это происходит для каждого элемента, вы можете видеть, как изменяется индекс Lucene на диске при просмотре каталога (количество файлов растет и изменяется по мере того, как вы наблюдаете за этим).

Если вы попробуете выполнить поиск на публичном сайте, когда это происходит, поиск может занять заметно больше времени, а при большой нагрузке может потребоваться до 15 секунд до завершения процесса переиндексации.

Я вижу, что этот процесс контролируется классом IndexingProvider. Есть ли способ переопределить этот класс и реализовать свой собственный?

Мы рассмотрели логику поиска и увидели, что при каждом запросе поиска создается объект IndexSearchContext, который в свою очередь создает новый IndexSearcher. Мы изменили часть логики таким образом, чтобы IndexSearchContext сохранялся как синглтон, что, конечно, означает, что несколько запросов могут обслуживаться одним и тем же Lucene IndexSearcher. Это резко сократило потребление памяти, поскольку для повышения производительности рекомендуется использовать один и тот же поисковик.

Однако при этом изменения в индексе не будут подхвачены до тех пор, пока не будет создан новый IndexSearcher. Нам нужен способ уведомить наш код о том, что процесс индексирования завершен, и тогда мы сможем сбросить наш объект singleton IndexSearchContext. Как мы можем интегрировать эту логику в код конфигурации Sitecore?

При восстановлении индекса вручную на это уходит всего около 5 секунд. Очевидно, что это эффективно удаляет индекс, а затем создает его заново, но почему обновление по элементам занимает так много времени? Нет ли лучшего способа обновления, не переходя от элемента к элементу и не влияя на публичный сайт?

Я ожидал, что эта проблема затронет и других, поэтому мне хотелось бы услышать, как люди решили эту проблему.

EDIT - дополнительная информация с форума 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 также пытается обновить его. Наверняка здесь что-то не так? Я не знаю, поэтому, пожалуйста, поправьте меня, если я ошибаюсь, вот как это выглядит, когда я просматриваю декомпилированный код без отладки.

5
задан Tim Peel 10 October 2011 в 11:07
поделиться