Решение
Реализация поставленной задачи достаточно тривиальное и сводится к нескольким шагам:
- Подключение к БД посредством JDBC
- Получение списка записей для индексации
- Преобразование записей в документы Lucene
- Индексация документов
- Запись индекса на диск
Проблемы и решения
При таком решении неизбежно возникают две главные проблемы: нехватка ресурсов и низкая скорость.
Нехватка памяти
Недостаточное количество ресурсов(памяти) вытекает из большого количества документов для индексации: требуется огромное количество памяти, чтобы содержать несколько миллионов записей. Данная проблема легко решается разбиением общего количество записей на порции меньшего размера. Конкретно для СУБД Oracle это делается при помощи конструкции с ROWNUM.
Низкая производительность
Проблемы с производительностью могут возникать в 2 местах: при получении записей из БД и при индексации. Как правило получение данных из БД это достаточно трудоемкая и долгая операция по сравнению с индексацией, поэтому наибольший эффект может быть достигнут при оптимизации именно взаимодействия с БД. Помещение документов в индекс не такая затратная операция, но даже на ней можно немного уменьшить общее время выполнения.
Производительность JDBC
Все рекомендации по увеличению производительности JDBC сводятся к оптимизации наиболее затратных операций и правильному использованию средств. Список наиболее существенных рекомендаций:
- Используйте пулы соединений - создание соединения с БД очень дорогая операция. Пул соединений позволит держать некоторое количество открытых соединений
- Контролируйте транзакции - по умолчанию фиксация изменений происходит после каждой операции неявно. Можно явно фиксировать изменения, например, после выполнения пакета операций, отключив автоматическую фиксацию изменений
- Закрывайте ресурсы явно - явное закрытие ресурса позволит сборщику мусора освободить дополнительную память
- Используйте правильные интерфейсы - Существует 3 типа интерфейсов Statement или операций getXXX в интерфейсе ResultSet. Использование подходящих классов и методов также снижает накладные расходы
- Используйте пакетные операции - пакетные операции получения и обновления данных существенно снижают накладные расходы
- Используйте PreparedStatement
- Оптимизируйте SQL - используйте получение нужного списка столбцов, вместо всех, смотрите планы выполнения, используйте индексы
- Используйте маленькие порции вместо больших
Производительность Lucene
Как писалось выше - индексация происходит куда быстрее получения данных, поэтому прежде всего надо убедиться необходимости ускорения индексации. Если индексация все же нужна, ниже приведен список наиболее существенных рекомендаций:
- Используйте последнюю версию библиотеки Lucene
- Используйте локальную файловую систему - создание индекса на удаленном устройстве происходит обычно медленнее, чем на локальном.
- Используйте быстрое железо - это касается подсистемы ввода/вывода и оперативной памяти. Используйте SSD, выделяйте как можно больше оперативной памяти
- Повторно используйте объекты - это касается всех типов объектов : IndexWriter, Document, Field
- Используйте явную фиксацию изменений используйте commit() вместо close(). Освобождение ресурсов очень затратная операция - используйте ее после завершения индексации.
- Отключайте возможности, которыми не пользуетесь
- Отключите использование Compound File формата - отключение данной опции позволить избежать накладных расходов по объединению всех файлов, принадлежащих одному сегменту, в файл контейнер. Правда не стоит забывать, что кол-во открытых во время индексации файлов существенно возрастет, что в свою очередь может привести к ошибке превышения допустимого количества открытых файлов
- Правильно формируйте поля для индексации - лучше индексировать одно текстовое поле, объединяющее все необходимые значения. При таком подходе сами поля могут находиться в индексе