#lucene.net #sitecore #sitecore6
#lucene.net #sitecore #sitecore6
Вопрос:
Мы находимся на Sitecore 6.4 и используем модуль расширенного поиска с общим исходным кодом и видим значительное снижение производительности поиска по сайту, когда запускается процесс переиндексации Sitecore и обновляет изменения в веб-базе данных.
Когда мы запускаем полную публикацию сайта, менеджер индексации фиксирует изменения и обрабатывает записи истории, которые, в свою очередь, переиндексируют каждый элемент, который был затронут. Поскольку это происходит для каждого элемента, вы можете видеть, как меняется индекс Lucene на диске при просмотре каталога (количество файлов растет и меняется по мере просмотра).
Если вы попытаетесь выполнить поиск на общедоступном веб-сайте, когда это происходит, поиск может занять заметно больше времени; а при большой нагрузке это может занять до 15 секунд дольше, пока процесс повторной индексации не завершится.
Я вижу, что этот процесс контролируется классом IndexingProvider . Есть ли какой-либо способ переопределить этот класс и реализовать наш собственный?
Мы рассмотрели логику поиска и видим, что объект IndexSearchContext создается каждый раз, когда запрашивается поиск, что, в свою очередь, создает новый IndexSearcher. Мы изменили часть логики, чтобы IndexSearchContext сохранялся как однотонный, что, конечно, означает, что одним и тем же средством поиска индексов Lucene может обслуживаться несколько запросов. Это значительно сократило потребление памяти, поскольку для повышения производительности рекомендуется использовать один и тот же поисковик.
Однако при этом изменения в индексе не будут обнаружены до тех пор, пока не будет создан новый IndexSearcher. Нам нужен способ уведомить наш код о завершении процесса индексирования, а затем мы можем сбросить наш одноэлементный объект IndexSearchContext. Как мы можем интегрировать эту логику в настроенный код Sitecore?
При перестроении индекса вручную для завершения требуется всего около 5 секунд. Очевидно, что это эффективно удаляет индекс, а затем создает все это снова, но почему обновление элемента за элементом занимает так много времени? Нет ли лучшего способа, с помощью которого процесс обновления может быть выполнен без перехода по элементам и не затрагивать общедоступный веб-сайт?
Я ожидал, что эта проблема затронет других, поэтому мне очень интересно услышать, как люди решили проблему.
РЕДАКТИРОВАТЬ — дополнительная информация с форума Sitecore
Ядро сайта.Похоже, что код поиска активно использует создание / удаление новых объектов 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.Индексирование.Метод Index.updateItem? Я думал, что это пространство имен обесценивается в версии 6.5, поэтому я удивлен, увидев связь между новым и старым пространством имен.
Похоже, что DatabaseCrawler обрабатывает обновление, которое удаляет элемент, а затем снова добавляет его в индекс; а затем старый Sitecore.Data.Индексирование.Индекс также пытается обновить его. Неужели здесь что-то не так? Я не знаю, хотя, пожалуйста, поправьте меня, если я ошибаюсь, это именно то, как это выглядит, когда я отслеживаю декомпилированный код без какой-либо отладки.
Комментарии:
1. Это похоже на продвинутый (и довольно аккуратный материал), который вы хотите сделать (и сделали до сих пор). Может быть, вам стоит попытаться поговорить об этом с Sitecore … если у вас есть улучшения, я уверен, что они будут рады услышать о них 🙂
2. Привет, Тим, я мог только представить это, когда индекс либо полностью перестраивается при каждой публикации, либо если у вас огромное количество пользователей, выполняющих поиск. У вас большое количество посетителей или что-то специально настроено для перестроения? Не могли бы вы попробовать отключить обновление индекса, а затем выполнить то же тестирование? Это может быть связано с публикацией в целом, а не только с индексацией.
3. @Йенс, спасибо, мы попытаемся отключить процесс индексации. Я не чувствую, что мы делаем что-то необычное с точки зрения размера контента или количества посетителей. Сайт относительно небольшой. Но нам нужно знать, что производительность будет постоянно увеличиваться. Если индекс полностью перестроен, он работает намного быстрее, около 5 секунд для полной перестройки. Обновление каждого элемента по одному может занять гораздо больше времени, чем вы бы изобразили.
4. Есть ли какая-то причина, по которой вы публикуете полный сайт, а не интеллектуальную публикацию? (Обычно я скрываю кнопку публикации сайта) Кроме того, я думаю, что это еще одна причина использовать рабочий процесс с автоматической публикацией в качестве последнего шага, где элементы могут индексироваться по мере необходимости. В вашем случае набор данных невелик, но я думаю, что есть веский аргумент против переиндексации всего, когда у клиента потенциально миллионы записей. Чтобы продолжить комментарий @JensMikkelsen, я широко использовал индексы и обнаружил, что они довольно эффективны, если вы понимаете, как работает Lucene.
Ответ №1:
Я бы порекомендовал две вещи:
-
Используйте расширенный поисковик базы данных (v2 — последняя версия), который охватывает
Sitecore.Search
пространство имен. Это делает использование Lucene очень простым.СЕТЬ с Sitecore. -
Ежедневно полностью перестраивайте индексы. Это дефрагментирует индексы, поскольку фрагментация с течением времени может снизить производительность (что может быть вашей проблемой здесь).
Комментарии:
1. Я попытался использовать ADC, это повлияет на ваше решение. Позже я удалил его.
Ответ №2:
Я сталкивался с подобными проблемами раньше. Когда я анализировал, что происходит, все время тратилось на открытие индекса для каждого поиска.
В итоге мы решили эту проблему, обойдя индексные классы Sitecore и перейдя непосредственно к Lucene. Lucene предоставляет метод «Повторного открытия», который открывает только измененные файлы сегментов, в отличие от всех файлов сегментов, как это делает Sitecore.
Итак, что мы сделали, это:
- Откройте программу чтения индексов, если у нас ее еще не было
- Создайте ссылку на него на уровне приложения, чтобы мы могли использовать его повторно
- При каждом вызове поиска «Повторно открыть» в программе чтения индексов приложения
- Поиск
Взгляните на Lucene.Net.Index.IndexReader.Повторно откройте документацию по методу
Вы можете создать средство чтения индексов из Sitecore.Поиск.Указатель.CreateReader()