Более быстрый способ пакетного сохранения с Hibernate?

У меня есть программа, которая читает построчный текстовый файл, создает объект-сущность Hibernate из каждой строки и сохраняет их. У меня есть несколько таких текстовых файлов для обработки, каждый из которых имеет около 300000 строк. Я обнаружил, что моя текущая реализация мучительно медленная, и мне интересно, могу ли я что-то сделать, чтобы улучшить ситуацию.

Мой основной метод обрабатывает текстовый файл построчно следующим образом:

// read the file line by line
FileInputStream fileInputStream = new FileInputStream(new File(fileName));
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
int lineCount = 0;
String line = bufferedReader.readLine();
while (line != null)
{
    // convert the line into an Observations object and persist it
    convertAndPersistObservationsLine(line);

    // if the number of lines we've processed has built up to the JDBC batch size then flush
    // and clear the session in order to control the size of Hibernate's first level cache
    lineCount++;
    if (lineCount % JDBC_CACHE_SIZE == 0)
    {
        observationsDao.flush();
        observationsDao.clear();
    }

    line = bufferedReader.readLine();
}

Метод convertAndPersistObservationsLine() просто разбивает текстовую строку на токены, создает новый объект сущности, заполняет поля сущности данными из токенов, а затем сохраняет объект через DAO, который вызывает метод Session.saveOrUpdate() Hibernate. Методы DAO flush() и clear() являются прямыми вызовами соответствующих методов Hibernate Session.

Свойство Hibernate 'hibernate.use_second_level_cache' имеет значение false, а свойство Hibernate 'hibernate.jdbc.batch_size' установлено равным 50, как и константа Java JDBC_CACHE_SIZE.

Может ли кто-нибудь предложить лучший способ сделать это или какие-то настройки, которые могут улучшить производительность этой программы пакетной загрузки?

Заранее спасибо за помощь.

--Джеймс

3 ответа

Сам код и конфигурация Hibernate выглядят правильно (под правильным я имею в виду, что они следуют идиомам пакетной вставки из документации). Но вот несколько дополнительных предложений:

Как уже упоминалось, убедитесь, что вы не используете генератор идентификаторов, который побеждает как IDENTITY, Когда используешь GenerationType.AUTOпоставщик сохраняемости выберет подходящую стратегию в зависимости от базы данных, поэтому, в зависимости от вашей базы данных, вам, возможно, придется изменить ее для TABLE или же SEQUENCE стратегия (потому что Hibernate может кэшировать идентификаторы, используя алгоритм hi-lo).

Также убедитесь, что Hibernate пакетируется, как и ожидалось. Для этого активируйте ведение журнала и следите за BatchingBatcher для отслеживания размера выполняемой партии (будет зарегистрировано).

В вашем конкретном случае вы можете рассмотреть возможность использования StatelessSession интерфейс (как только проблема будет решена, конечно).

Несколько вещей:

  1. Можете ли вы дать количественную оценку "мучительно медленно"? Сколько вкладок в секунду вы достигаете? Как вы думаете, какой курс вы должны иметь вместо этого? Какой тип нагрузки находится под самой базой данных? Другие одновременно читают со стола?

  2. Как вы подключаетесь к базе данных? Все ли это происходит в одной транзакции с повторным использованием одного и того же соединения?

  3. Вы случайно не используете identity идентификатор? В документации говорится, что пакетирование JDBC отключено автоматически, если вы:

Hibernate отключает пакетную вставку на уровне JDBC прозрачно, если вы используете генератор идентификатора идентификатора.

Если вы используете MySQL, вы можете захотеть включить rewriteBatchedStatements, поскольку MySQL не поддерживает пакетную форму привязок параметров оператора подготовки. Он перезапишет ваши операторы вставки в форму как "INSERT INTO YourEntity VALUES (...), (...), (...)".

Пожалуйста, обратитесь к: http://shengchien.blogspot.com/2010/10/hibernate-batch-processing-with-mysql.html

Другие вопросы по тегам