#java #hibernate #jdbc
#java #спящий режим #jdbc
Вопрос:
Я хочу обновить значение столбца в таблице, содержащей 800 тыс. строк. Итак, я создал простое Java-приложение с Hibernate 4.3.6.Final в качестве среды ORM.
Я настроил пакет JDBC с 45 в качестве значения и отключил использование кэша второго уровня.
<property name="hibernate.jdbc.batch_size">45</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
Могу ли я увеличить batch_size
, например, до 200? Потому что в документах гибернации они упоминают:
Перед пакетной обработкой включите пакетную обработку JDBC. Чтобы включить пакетную обработку JDBC, установите для свойства hibernate.jdbc.batch_size значение от 10 до 50.
Это код (упрощенный):
session.beginTransaction();
List<MyEntity> entities = findAllEntities();
logger.info("Number of fetched rows: " entities.size());
int count = 0;
for (MyEntity entity : entities) {
// change some fields of the entity
session.update(entity);
if ( count % HIBERNATE_BACH_SIZE == 0 ) {
//flush a batch of updates and release memory:
session.flush();
session.clear();
}
}
session.getTransaction().commit();
Комментарии:
1. зачем вам это нужно?
2. Я выполняю анализ со значениями этого столбца. Итак, каждый раз, когда я меняю способ генерации значения этого столбца, мне нужно подождать 3 часа или около того.
3. Можете ли вы поделиться своим кодом? Каким образом вы выполняете обновление?
4. @Stultuske абсолютно.
5. @akortex91 пожалуйста, проверьте еще раз, я отредактировал свой пост.
Ответ №1:
Извлечение всех объектов и последующее перебирание их по одному довольно утомительно и всегда приводит к неоптимальной производительности.
Поскольку кажется, что вы выполняете безусловное обновление (т.Е. Нет проверок, чтобы определить, какой объект будет обновлять свои поля), вы должны использовать простой HQL
запрос для выполнения обновления за одно действие.
Например, учитывая таблицу, которую вы хотите обновить MyEntity
, ваш запрос будет выглядеть следующим образом:
int rows = session.createQuery("UPDATE MyEntity ME SET me.myField1=:newField1, me.myField2=:newField2)
.setString("newField1", "Something")
.setString("newField2", "Something")
.executeUpdate();
Использование этого должно значительно повысить производительность.
Комментарии:
1. За последнее десятилетие было сделано множество улучшений / улучшений производительности корпоративного программного обеспечения при неправильном использовании ORM-фреймворков — этот совет прямо здесь модифицируется. Однако единственное, что я бы добавил, это использовать соответствующий язык запросов для проекта, в котором вы работаете. Если вы используете hibernate-jpa, используйте JPQL. В противном случае, HQL. Вы, конечно, можете изменять определения свойств между средами, что становится вопросом конфигурации — и у вас должны быть средства изменения параметров конфигурации без необходимости перекомпиляции / перестройки вашего приложения. Это другая проблема.
2. @bvarner Очень верно, что вы упомянули, но, учитывая ограниченные детали, предоставленные OP, было бы трудно догадаться, что они на самом деле используют. Основная идея ответа заключалась в том, чтобы направить его в правильном направлении, то есть избежать использования ORM для того, чего мы пытались достичь.