Spring, Hibernate - пакетная обработка больших объемов данных с хорошей производительностью - PullRequest
2 голосов
/ 10 января 2012

Представьте, что у вас есть большой объем данных в базе данных ок.~ 100Mb.Нам нужно как-то обработать все данные (обновить или экспортировать в другое место).Как реализовать эту задачу с хорошей производительностью?Как настроить распространение транзакции?

Пример 1 # (с плохой производительностью):

@Singleton
public ServiceBean {

 procesAllData(){

   List<Entity> entityList = dao.findAll();

   for(...){
     process(entity);
   }

 }

 private void process(Entity ent){
  //data processing    
  //saves data back (UPDATE operation) or exports to somewhere else (just READs from DB)
 }

}

Что можно улучшить здесь?

По моему мнению:

  1. Я бы установил размер пакета hibernate (см. Документацию по hibernate для обработки пакетов).
  2. Я бы разделил ServiceBean на два компонента Spring с разныминастройки транзакций.Метод processAllData () должен завершиться из-за транзакции, потому что он работает с большими объемами данных и потенциальный откат не будет «быстрым» (я полагаю).Процесс метода (сущность сущности) будет выполняться в транзакции - нет ничего сложного в откате в случае одной сущности данных.

Согласны ли вы?Любые советы?

Ответы [ 2 ]

2 голосов
/ 10 января 2012

Вот 2 основные стратегии:

  1. Пакетирование JDBC: установите размер пакета JDBC, обычно где-то между 20 и 50 (hibernate.jdbc.batch_size). Если вы смешиваете и сопоставляете операции C / U / D объекта, убедитесь, что Hibernate настроен для упорядочивания вставок и обновлений, в противном случае он не будет пакетным (hibernate.order_inserts и hibernate.order_updates). И при выполнении пакетирования обязательно убедитесь, что вы clear() свой Session, чтобы не столкнуться с проблемами памяти во время большой транзакции.
  2. Объединенные операторы SQL: реализуйте интерфейс Hibernate Work и используйте свой класс реализации (или анонимный внутренний класс) для запуска собственного SQL для соединения JDBC. Конкатенация SQL-кода, написанного вручную, через точку с запятой (работает в большинстве БД), а затем обработка этого SQL-кода через doWork. Эта стратегия позволяет вам использовать координатор транзакций Hibernate, используя при этом всю мощь собственного SQL.

Как правило, вы обнаружите, что независимо от того, насколько быстро вы сможете получить свой ОО-код, использование трюков с БД, таких как объединение операторов SQL, будет быстрее.

1 голос
/ 10 января 2012

Здесь следует иметь в виду несколько вещей:

  1. Загрузка всех объектов в память методом findAll может привести к исключениям OOM.

  2. Вам необходимо избегать присоединения всех сущностей к сеансу - поскольку каждый раз, когда hibernate выполняет сброс, ему нужно будет проверять каждую присоединенную сущность. Это быстро остановит вашу обработку.

Hibernate предоставляет сеанс без сохранения состояния, который можно использовать с прокручиваемым набором результатов для прокрутки объектов по одному - документы здесь . Затем вы можете использовать этот сеанс для обновления объекта, даже не подключая его к сеансу.

Другая альтернатива - использовать сеанс с сохранением состояния, но очищать сеанс через регулярные интервалы, как показано здесь .

Надеюсь, это полезный совет.

...