В этой статье описывается метод обработки пакетов спящего пакета массовых данных. Поделитесь этим для вашей ссылки, следующим образом:
Обработка Hibernate Packation Массовые суммы на самом деле нежелательны с точки зрения производительности и потрачены впустую много памяти. Из своего механизма Hibernate сначала проверяет данные, которые соответствуют условиям, ставят их в память, а затем выполняют операции. Производительность очень неудовлетворительная в фактическом использовании. В моем фактическом использовании данные следующего третьего решения для оптимизации: 100 000 фрагментов данных вставлены в базу данных, которая занимает около 30 минут. Ха -ха, слабый. (I вставил 1000 000 фрагментов данных за 10 минут (поля относительно невелики))
Есть три способа справиться с этим, чтобы решить проблемы с производительностью:
1: Обход API Hibernate и непосредственно используйте API JDBC. Этот метод имеет лучшую производительность. Это также самое быстрое.
2: Используйте сохраненные процедуры.
3: Используйте API Hibernate для выполнения регулярной партии. Там могут быть изменения, и изменение изменится. Когда мы находим определенную сумму, мы можем удалить данные во времени после завершения операции, session.flush (); session.evict (xx набор объектов); Это также может сэкономить некоторые потери производительности. Это «определенное количество» необходимо использовать в качестве количественной ссылки на основе фактических условий. Обычно около 30-60, но эффект все еще не идеален.
1: Обход API Hibernate и сделайте это непосредственно через API JDBC. Этот метод имеет лучшую производительность и самый быстрый. (Пример - операция обновления)
Транзакция tx = session.beginTransaction (); // Обратите внимание, что вы используете граничное соединение границ транзакции Hibernate conn = session.connection (); Подготовленный Statatement STMT = conn.PreparedStatement («Обновить клиент как c Set C.Sarlary = C.Sarlary+1, где C.Sarlary> 1000»); stmt.excuteupdate (); tx.commit (); // Обратите внимание, что вы используете границу транзакции Hibernate
В этом апплете он использует API, который напрямую вызывает JDBC для доступа к базе данных, что очень эффективно. Избегайте проблем с производительностью, вызванными Hibernate, сначала запросом и загрузкой в память, а затем выполняют операции.
2: Используйте сохраненные процедуры. Однако этот метод не рекомендуется использовать из -за удобства портативности и развертывания программы. (Пример - операция обновления)
Если базовая база данных (например, Oracle) поддерживает хранимые процедуры, пакетные обновления также могут быть выполнены с помощью хранимых процедур. Хранимые процедуры, работающие непосредственно в базе данных, быстрее. В базе данных Oracle может быть определена хранящаяся процедура с именем BatchUpdateCustomer (), код выглядит следующим образом:
Копия кода выглядит следующим образом: Создать или заменить процедуру batchupdateCustomer (p_age по числу) в качестве начала обновления клиентов Установите возраст = возраст+1, где возраст> p_age; end;
Приведенная выше хранящаяся процедура имеет параметр p_age, который представляет возраст клиента. Приложение может вызвать хранимую процедуру следующими способами:
tx = session.begintransaction (); connection con = session.connection (); string procusure = "{call batchupdatecustomer (?)}"; callableStatement cstmt = con.preparecall (процедура); cstmt.setint (1, 0); // Установить возрастный параметр на 0cstmt.executeupdate (); tx.commit ();Как видно из вышеуказанной программы, приложение также должно обойти API Hibernate и непосредственно вызывать хранимые процедуры через API JDBC.
3: Используйте API Hibernate для выполнения регулярной партии. Там могут быть изменения, и изменение изменится. Когда мы находим определенную сумму, мы можем удалить данные во времени после завершения операции, session.flush (); session.evict (xx набор объектов); Это также может сэкономить некоторые потери производительности. Это «определенное количество» должно быть количественной ссылкой, основанной на фактических условиях ...
(Пример - операция сохранения)
Бизнес -логика: мы хотим вставить 10 0000 фрагментов данных в базу данных
tx = session.begintransaction (); for (int i = 0; i <100000; i ++) {customer custom = new Customer (); Custom.SetName («Пользователь»+I); Session.Save (Custom); if (i%50 == 0) // Использовать каждые 50 данных в качестве обработчивого блока, что я упоминал выше, эта количества должна рассматриваться как соответствующая ().Это будет держать систему в стабильном диапазоне ...
В процессе разработки проекта, благодаря требованиям проекта, нам часто необходимо вставить большое количество данных в базу данных. Есть десятки тысяч, десятки тысяч, десятки миллионов, даже десятки миллионов из них. Если вы используете Hibernate для вставки данных на этом уровне, может произойти исключение. Общим исключением является OutOfMemoryError (исключение переполнения памяти).
Во -первых, давайте кратко рассмотрим механизм операции вставки с зимством. Hibernate должен поддерживать свой внутренний кэш. Когда мы выполним операцию вставки, мы поместим все объекты для работы в нашем внутреннем кэше для управления.
Когда дело доходит до кеша Hibernate, Hibernate имеет теории внутреннего кеша и вторичного кеша. Поскольку Hibernate имеет различные механизмы управления для этих двух кэшей, мы можем настроить его размер в отношении вторичного кэша, в то время как для внутренних кэшей Hibernate применяет отношение «потоковой передачи», и в его способности нет ограничения. Теперь суть проблемы найдена. Когда мы вставляем массовые данные, так много объектов будет включено во внутренний кэш (внутренний кэш кэшируется в памяти), так что ваша системная память будет кусочнее. Если система наконец «жареная», это разумно.
Давайте подумаем о том, как лучше справиться с этой проблемой? Некоторые условия разработки должны быть обработаны с использованием Hibernate, и, конечно, некоторые проекты более гибки, и вы можете найти другие методы.
Здесь я рекомендую два метода:
(1): оптимизируйте Hibernate и используйте метод сегментированной вставки для очистки кэша во времени в программе.
(2): обходите API Hibernate API и сделайте пакетную вставку непосредственно через API JDBC. Этот метод имеет лучшую производительность и самый быстрый.
Для метода 1 выше, основная идея: оптимизировать Hibernate, установите параметр hibernate.jdbc.batch_size в файле конфигурации, чтобы указать количество SQL, представленное каждый раз; Программа использует метод очистки кэша во времени при сегментированной вставке (сеанс реализует асинхронную запись записи, что позволяет Hibernate явно записывать операции), то есть очистить их от внутреннего кэша во времени после вставки определенной суммы данных и освобождает окрестивную память.
Чтобы установить параметр hibernate.jdbc.batch_size, вы можете обратиться к следующей конфигурации.
<hibernate-configuration> <session-factory>… <name = "hibernate.jdbc.batch_size"> 50 </property>… <Session-factory> <hibernate-configuration>
Причиной настройки параметра hibernate.jdbc.batch_size является чтение базы данных как можно меньше. Чем больше значение параметра hibernate.jdbc.batch_size, тем меньше времени, когда вы читаете базу данных, и чем быстрее скорость. Из приведенной выше конфигурации видно, что Hibernate ждет, пока программа не наберет 50 SQL, прежде чем отправлять ее партиями.
Автор также думает, что значение параметра hibernate.jdbc.batch_size не может быть установлен как можно большим, и его еще предстоит обсудить с точки зрения производительности. Это требует рассмотрения реальной ситуации и установления ее в зависимости от необходимости. Как правило, установка 30 или 50 может удовлетворить потребности.
С точки зрения реализации программы, автор принимает в качестве примера вставку 10 000 фрагментов данных,
Session Session = hibernateUtil.currentSession (); Transatcion tx = session.beginTransaction (); для (int i = 0; i <10000; i ++) {Студент ST = новый студент (); St.SetName ("feifei"); Session.save (ST); if (i%50 == 0) // Использование каждых 50 данных в виде обработки. // Сохраняйте синхронный с сеансом данных базы данных.clear (); // Очистить все данные, кэшированные внутри, и выпустить занятую память во времени}} tx.commit (); ...В соответствии с определенной шкалой данных этот подход может поддерживать ресурсы системной памяти в относительно стабильном диапазоне.
Примечание: кеш второго уровня, упомянутый ранее, необходим для того, чтобы я упомянул об этом здесь. Если вторичный кэш включен, чтобы поддерживать вторичный кэш, Hibernate заряжает соответствующие данные во вторичный кэш, когда мы выполняем вставку, обновление и удаление операций. В результате производительности будет огромная потеря, поэтому автор рекомендует отключить кэш 2 -го уровня в обработке партии.
Для метода 2 используется традиционная партийная обработка JDBC, и для его обработки используется API JDBC.
Пожалуйста, обратитесь к Java Packation Processing and Seffection SQL.
Глядя на приведенный выше код, вы всегда чувствуете, что что -то неуместное? Да, разве вы не заметили это! Это все еще традиционное программирование JDBC, без спящего вкуса.
Приведенный выше код может быть изменен на следующее:
Транзакция tx = session.beginTransaction (); // Использование сгибающей транзакции подключение connect = session.connection (); PrepareStatement stmt = conn.prepareStatement ("вставьте в t_student (name) values (?)"); for (int j = 0; j ++; j <200) {for (int i = 0; i ++; j <50) {stmt.setString (1, "feifei");}} stmt.executeUpdate (); tx.commit (); // Использовать границу обработки транзакций сгибания ...Это изменение будет иметь спящий вкус. После тестирования автор использует API JDBC для партийной обработки, которая почти в 10 раз выше производительности, чем использование API Hibernate. Это, несомненно, доминирующее исполнение JDBC.
В пакетном обновлении и удалении Hibernate2 для операций обновления партии Hibernate обнаруживает данные, которые соответствуют требованиям, а затем выполняют операцию обновления. То же самое относится и к удалению партии. Сначала выясните данные, которые соответствуют условиям, а затем выполните операцию удаления.
У этого есть два основных недостатка:
(1): занимает много памяти.
(2): При обработке массовых данных выполнение оператора Update/Delete представляет собой огромную сумму, а оператор Update/Delete может работать только один объект. Вполне возможно, что производительность базы данных низкая, если она часто эксплуатируется.
После выпуска Hibernate3 было введено объемное обновление/удаление для операций с обновлением пакетов/удаления. Принцип состоит в том, чтобы завершить пакетное обновление/удаление операций через операции HQL, который очень похож на операции JDBC обновления/удаления. С точки зрения производительности, существует большое улучшение по сравнению с обновлениями пакетов/удалением Hibernate2.
Транзакция tx = session.beginsession (); string hql = "удалить студент"; Query Query = session.createequery (hql); int size = Query.executeUpdate (); tx.commit (); ... ...
Консоль выводит только один оператор удаления Hibernate: удалить из T_STUDENT. Выполнение оператора меньше, и производительность почти такая же, как использование JDBC. Это хороший способ повысить производительность. Конечно, чтобы иметь лучшую производительность, автор рекомендует, чтобы пакетные обновления и операции по удалению по -прежнему использовали JDBC. Методы и базовые точки знания в основном такие же, как приведенный выше метод 2 вставки партии, поэтому я не буду описать его избыточно здесь.
Здесь я предоставляю другой метод, который должен рассмотреть возможность повышения производительности со стороны базы данных и вызовать хранимые процедуры на стороне программы Hibernate. Хранилированные процедуры, выполняемые на стороне базы данных, быстрее. Принимая обновления пакетов в качестве примера, приведен справочный код.
Во -первых, создайте хранимую процедуру с именем BatchupDateStudent на стороне базы данных:
Создать или заменить производство batchupdateStudent (a в числе) asbeginupdate Ученик набор возраста = возраст+1, где возраст> a; end;
Код вызова выглядит следующим образом:
Transaction tx = session.beginsession (); connection conn = session.connection (); string pd = "… {call batchupdatestudent (?)}"; Callablestatement cstmt = conn.preparecall (pd); cstmt.setint (1, 20); // Установить возрастный параметр на 20tx.commit ();Наблюдая за приведенным выше кодом, он также обходит API Hibernate и использует API JDBC для вызова хранимых процедур, и использует границы транзакций Hibernate. Хранилированные процедуры, несомненно, являются хорошим способом повышения производительности обработки партии. Они работают непосредственно со стороной базы данных и в некоторой степени переносят давление пакетной обработки в базу данных.
PostScript
В этой статье обсуждаются операции по обработке пакетной обработки Hibernate, и отправной точкой является рассмотрение повышения производительности, и она обеспечивает лишь небольшой аспект повышения производительности.
Независимо от того, какой метод принят, он должен рассматриваться на основе фактических условий. Предоставление пользователям эффективной и стабильной системы, которая отвечает их потребностям, является главным приоритетом.
Я надеюсь, что эта статья будет полезна для спящих программ.