Lucene индексация больших объемов данных, хранящихся в БД Oracle

Lucene индексация больших объемов данных, хранящихся в БД Oracle

В статье будут рассмотрены особенности решения задачи полнотекстовой индексации больших объемов данных, хранящихся в БД, на примере связки Apache Lucene и СУБД Oracle.

Задача

Необходимо создать полнотекстовый индекс для сквозного поиска по данным, хранящимся в различных таблицах БД. В качестве поискового движка используется Apache Lucene, в качестве СУБД - Oracle. Совокупное количество записей в БД превышает несколько миллионов.

Решение

Реализация поставленной задачи достаточно тривиальное и сводится к нескольким шагам:

  1. Подключение к БД посредством JDBC
  2. Получение списка записей для индексации
  3. Преобразование записей в документы Lucene
  4. Индексация документов
  5. Запись индекса на диск

Проблемы и решения

При таком решении неизбежно возникают две главные проблемы: нехватка ресурсов и низкая скорость.

Нехватка памяти

Недостаточное количество ресурсов(памяти) вытекает из большого количества документов для индексации: требуется огромное количество памяти, чтобы содержать несколько миллионов записей. Данная проблема легко решается разбиением общего количество записей на порции меньшего размера. Конкретно для СУБД Oracle это делается при помощи конструкции с ROWNUM.

Низкая производительность

Проблемы с производительностью могут возникать в 2 местах: при получении записей из БД и при индексации. Как правило получение данных из БД это достаточно трудоемкая и долгая операция по сравнению с индексацией, поэтому наибольший эффект может быть достигнут при оптимизации именно взаимодействия с БД. Помещение документов в индекс не такая затратная операция, но даже на ней можно немного уменьшить общее время выполнения.

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

Все рекомендации по увеличению производительности JDBC сводятся к оптимизации наиболее затратных операций и правильному использованию средств. Список наиболее существенных рекомендаций:

  • Используйте пулы соединений - создание соединения с БД очень дорогая операция. Пул соединений позволит держать некоторое количество открытых соединений
  • Контролируйте транзакции - по умолчанию фиксация изменений происходит после каждой операции неявно. Можно явно фиксировать изменения, например, после выполнения пакета операций, отключив автоматическую фиксацию изменений
  • Закрывайте ресурсы явно - явное закрытие ресурса позволит сборщику мусора освободить дополнительную память
  • Используйте правильные интерфейсы - Существует 3 типа интерфейсов Statement или операций getXXX в интерфейсе ResultSet. Использование подходящих классов и методов также снижает накладные расходы
  • Используйте пакетные операции - пакетные операции получения и обновления данных существенно снижают накладные расходы
  • Используйте PreparedStatement
  • Оптимизируйте SQL - используйте получение нужного списка столбцов, вместо всех, смотрите планы выполнения, используйте индексы
  • Используйте маленькие порции вместо больших

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

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

  • Используйте последнюю версию библиотеки Lucene
  • Используйте локальную файловую систему - создание индекса на удаленном устройстве происходит обычно медленнее, чем на локальном.
  • Используйте быстрое железо - это касается подсистемы ввода/вывода и оперативной памяти. Используйте SSD, выделяйте как можно больше оперативной памяти
  • Повторно используйте объекты - это касается всех типов объектов : IndexWriter, Document, Field
  • Используйте явную фиксацию изменений используйте commit() вместо close(). Освобождение ресурсов очень затратная операция - используйте ее после завершения индексации.
  • Отключайте возможности, которыми не пользуетесь
  • Отключите использование Compound File формата - отключение данной опции позволить избежать накладных расходов по объединению всех файлов, принадлежащих одному сегменту, в файл контейнер. Правда не стоит забывать, что кол-во открытых во время индексации файлов существенно возрастет, что в свою очередь может привести к ошибке превышения допустимого количества открытых файлов
  • Правильно формируйте поля для индексации - лучше индексировать одно текстовое поле, объединяющее все необходимые значения. При таком подходе сами поля могут находиться в индексе

Источники