Статьи

Удовольствие от модуля многогранного поиска Lucene

В наши дни  многогранный поиск и навигация  являются обычным явлением, и пользователи привыкли ожидать и полагаться на него. 

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

Модуль фасетов не был интегрирован ни в  Solr , который имеет  совершенно другую реализацию , ни в  ElasticSearch , который также имеет свою собственную  реализациюБобо это еще один аспект реализации! Я уверен, что есть и другие … 

Модуль фасетов может вычислять обычные значения для каждого фасета, но также имеет расширенные функции, такие как агрегаты, отличные от количества попаданий, выборки (для лучшей производительности при большом количестве попаданий) и дополнения агрегации ( для повышения производительности, когда число попаданий превышает половину индекса). Все аспекты являются иерархическими, поэтому приложение может свободно индексировать произвольную древовидную структуру для каждого документа. Начиная с версии 4.1, фазовый модуль будет  полностью поддерживать  поиск почти в реальном времени (NRT). 

Ночные тесты производительности Lucene

Мне было любопытно узнать производительность фасетного поиска, поэтому я добавил фреймы дат, проиндексированные в виде year/month/day иерархии, в  ночные тесты Lucene., В частности, я добавил огранку для всех TermQuerys, которые уже были протестированы, и теперь мы можем наблюдать за  этим графиком,  чтобы отслеживать эффективность нашего многогранного поиска с течением времени. Поле даты является  timestamp самой последней версией каждой страницы Википедии. 

Простые тесты производительности

Я также провел несколько простых начальных тестов в недавнем (5/2/2012)  английском экспорте из Википедии , который содержит 30,2 ГБ простого текста в 33,3 млн. Документов. По умолчанию поиск в фасете возвращает количество всех значений фасетов в корневом узле (в данном случае, в годах):

     Date (3994646)
       2012 (1990192)
       2011 (752327)
       2010 (380977)
       2009 (275152)
       2008 (271543)
       2007 (211688)
       2006 (98809)
       2005 (12846)
       2004 (1105)
       2003 (7)

Интересно, что в 2012 году такой высокий показатель, хотя этот экспорт включает только первые пять месяцев и два дня 2012 года. Страницы Википедии очень активно редактируются! 

Индекс поиска с фасетами вырос лишь незначительно (~ 2,3%, с 12,5 ГБ до 12,8 ГБ) из-за дополнительного индексированного поля фасетов. Индекс таксономии, который представляет собой отдельный индекс, используемый для отображения фасетов на фиксированные целочисленные коды, был крошечным: всего 120 КБ. Чем больше у вас уникальных значений фасетов, тем больше будет этот индекс. 

Затем я сравнил эффективность поиска с и без огранки. Простое 
TermQuery (
party), соответствующее чуть более миллиона обращений, составило 51,2 запроса в секунду (QPS) без фасетов и 3,4 QPS с фасетами. Хотя это несколько страшное замедление, это худший вариант развития событий: 
TermQuery очень дешево выполнить и может легко соответствовать большому количеству хитов. Стоимость огранки пропорциональна количеству попаданий. Было бы неплохо ускорить это (патчи приветствуются!). 

Я также проверил hard 
PhraseQuery (
"the village"), сопоставив 194 тыс. Обращений: 3,8 QPS без фасетов и 2,8 QPS с фасетами, что является меньшим ударом, поскольку 
PhraseQuery требует больше работы для соответствия каждому удару и в целом соответствует меньшему количеству попаданий. 

Загрузка данных фасетов в оперативную память.

Для приведенных выше результатов я использовал фасетные значения по умолчанию, где значения фасетов для каждого документа остаются на диске во время агрегации. Если у вас достаточно оперативной памяти, вы также можете загрузить все значения фасетов в оперативную память, используя 
CategoryListCache класс. Я проверил это, и это дало хорошие ускорения: он 
TermQuery был на 73% быстрее (до 6,0 QPS) и 
PhraseQuery был на 19% быстрее. 

Однако есть и недостатки: инициализация требует много времени (4,6 секунды в моем тесте) и не является NRT-дружественной, хотя это не должно быть так сложно исправить (исправления приветствуются!). По словам Лусена, для этого также потребовалось 1,9 ГБ оперативной памяти 
RamUsageEstimator. Мы должны быть в состоянии сократить использование этой оперативной памяти, переключившись на  реализацию быстро упакованных целочисленных операций Lucene 
с текущей версии int [] [], которую он использует сегодня, или используя 
DocValues для хранения данные фасетов для каждого документа. Я только что открыл
LUCENE-4602  для изучения, 
DocValues и первые результаты выглядят очень многообещающе. 

отбор проб

Затем я попытался выполнить выборку, где модуль фасетов посещает 1% обращений (по умолчанию), и для них учитываются только агрегаты. В режиме по умолчанию эта выборка используется только для поиска значений N верхнего фасета, а затем второй проход вычисляет правильное число для каждого из этих значений. Это хорошо подходит, когда таксономия широкая и плоская, а счет довольно равномерно распределен. Я проверил это, но результаты были медленнее, потому что таксономия даты не широка и плоска и имеет довольно однобокие показатели (в 2012 г. большинство хитов). 

Вы также можете пропустить второй проход, а затем представить приблизительное количество или процентное значение для пользователя. Я проверил это и увидел значительный прирост: он 
TermQuery был на 248% (в 2,5 раза) быстрее (до 12,2 QPS) и 
PhraseQuery был на 29% быстрее (до 3,6 QPS). Выборка также вполне настраивается: вы можете установить минимальный и максимальный размеры выборки, соотношение выборки, порог, при котором выборка не должна выполняться, и т. Д. 

Модуль фасетов Lucene упрощает добавление фасетов в поисковое приложение и предлагает полезные функции. такие как выборка, альтернативные агрегаты, дополнения, кэширование в ОЗУ и полностью настраиваемые интерфейсы для многих аспектов фасетирования. Я надеюсь, что мы сможем сократить потребление оперативной памяти для кэширования и повысить общую производительность с течением времени.