В наши дни многогранный поиск и навигация являются обычным явлением, и пользователи привыкли ожидать и полагаться на него.
Модуль фасетов Lucene, впервые появившийся в выпуске 3.4.0, предлагает мощную реализацию, которая упрощает добавление граненого пользовательского интерфейса в ваше поисковое приложение. Шай Эрера написал хороший обзор здесь и в своем втором посте проиллюстрировал прекрасные примеры для начинающих .
Модуль фасетов не был интегрирован ни в Solr , который имеет совершенно другую реализацию , ни в ElasticSearch , который также имеет свою собственную реализацию . Бобо это еще один аспект реализации! Я уверен, что есть и другие …
Модуль фасетов может вычислять обычные значения для каждого фасета, но также имеет расширенные функции, такие как агрегаты, отличные от количества попаданий, выборки (для лучшей производительности при большом количестве попаданий) и дополнения агрегации ( для повышения производительности, когда число попаданий превышает половину индекса). Все аспекты являются иерархическими, поэтому приложение может свободно индексировать произвольную древовидную структуру для каждого документа. Начиная с версии 4.1, фазовый модуль будет полностью поддерживать поиск почти в реальном времени (NRT).
Ночные тесты производительности Lucene
Мне было любопытно узнать производительность фасетного поиска, поэтому я добавил фреймы дат, проиндексированные в виде year/month/day
иерархии, в ночные тесты Lucene., В частности, я добавил огранку для всех TermQuery
s, которые уже были протестированы, и теперь мы можем наблюдать за этим графиком, чтобы отслеживать эффективность нашего многогранного поиска с течением времени. Поле даты является 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 упрощает добавление фасетов в поисковое приложение и предлагает полезные функции. такие как выборка, альтернативные агрегаты, дополнения, кэширование в ОЗУ и полностью настраиваемые интерфейсы для многих аспектов фасетирования. Я надеюсь, что мы сможем сократить потребление оперативной памяти для кэширования и повысить общую производительность с течением времени.