Обычная гибернативная производительность

Мы только что закончили, чтобы профилировать наше приложение. (она начинает медленно). проблема кажется «в спящем режиме».

Это наследие. Кто работает, и это работает. Оправдательная реляционная шема тоже в порядке.

Но какой-то запрос медленный, как черт.

Таким образом, мы будем благодарны за вклад в общую и обычную ошибку, сделанные с помощью спящего режима, которые в конечном итоге получают медленный ответ.

Пример: Желание вместо Lazy может значительно изменить время отклика ….


Изменить: Как обычно, чтение руководства часто является хорошей идеей. Целая глава охватывает эту тему здесь:

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

Одна из самых распространенных ошибок – печально известная проблема с n + 1 . По умолчанию Hibernate не загружает данные, которые вы не запрашивали. Это уменьшает потребление памяти, но предоставляет вам проблему n + 1, которая может быть устранена путем переключения на правильную страtagsю выборки для извлечения всех данных, необходимых для загрузки объектов в их надлежащим образом инициализированном состоянии.

Но также не извлекайте слишком много или вы столкнетесь с противоположной проблемой, проблемой декартовых продуктов : вместо выполнения многих операторов SQL вы можете создать инструкции, которые извлекают слишком много данных.

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

Мои рекомендации:

  • сначала активировать ведение журнала SQL на уровне Hibernate
  • используйте критические варианты использования (20% используют 80% времени) или даже все из них, если у вас есть эта роскошь
  • выявлять подозрительные запросы и оптимизировать план извлечения, проверять, используются ли индексы надлежащим образом и т. д.
  • привлекать администраторов баз данных

Я хотел бы поддержать все, что сказал Паскаль, и просто упомянуть в дополнение к тому, что одно решение для «слишком большой проблемы с данными» заключается в использовании Hibernate Projections и извлечении данных в плоский DTO, который состоит только из столбцов необходимо. Это определенно вариант, когда вы не планируете обновлять данные в этом сеансе Hibernate, поэтому для этого не нужны сопоставленные объекты. Взято из этой статьи , в которой содержится больше советов по производительности Hibernate.

Наиболее распространенными ошибками являются выбор N + 1, которые скрыты за кулисами. Как правило, они не обнаруживаются до производства, а обычные профилографы не очень хорошо раскрывают их.

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

http://zeroturnaround.com/blog/hibernate-orm-with-xrebel-revealing-multi-query-issues-with-an-interactive-profiler/

XRebel показывает SQL-запросы

Одна вещь, которая произошла в моей компании, приходит на ум. Вы могли видеть, загружает ли объект объект, загружающий некоторый serialized объект, который будет десериализован каждый раз, когда объект загружается. Кроме того, при совершении транзакции hibernate может сделать flush() для вас (настраивается). Если он сбрасывается, чтобы сохранить устойчивость, он выполнит сравнение по совершенству и такому в базе данных. В этом случае он будет сравнивать serialized объект, который занимает много времени.

Еще одна вещь, которую вы можете сделать, это проверить, есть ли у вас ненужное каскадное @Cascade({CascadeType.PERSIST, CascadeType.SAVE_UPDATE}) т. @Cascade({CascadeType.PERSIST, CascadeType.SAVE_UPDATE}) в столбцах.

Еще одна вещь, которую вы можете сделать, которая специально не связана с hibernate, заключается в том, что вы создаете view s для выполнения одного запроса, вместо того, чтобы делать много и много запросов для разных таблиц. Это имело огромное значение для нас по определенной функции.

Как уже отмечали ребята, производительность Hibernate – это правильные настройки. Когда-то я смог улучшить скорость обновления кеша учетных данных в 10 раз (от 2 до 200 мс), переключившись на сеанс без сохранения состояния (этот конкретный код не зависел ни от какого типа ленивой выборки, чтобы я мог спокойно делать то, что я сделал) ,

Сопоставление отношений m: n и n: 1 является корнем для частых проблем с Hibernate.

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

Если вы хотите простой, быстрый и легкий подход, я могу порекомендовать fjorm

Отказ от ответственности: я являюсь основателем проекта fjorm

Как уже упоминалось, проблема N + 1 является распространенной проблемой в приложениях JPA. В настоящее время я работаю над инструментом для раннего обнаружения этих проблем в ваших модульных тестах и ​​в тестовых средах. Он называется JDBC Sniffer , он является открытым исходным кодом и полностью свободен

Он позволяет отслеживать количество запросов, выполняемых в тестовых средах, непосредственно в вашем браузере: введите описание изображения здесь

Кроме того, он предоставляет extensino для популярных модhive тестирования модhive, чтобы поймать проблему N + 1, в то время как вы все еще разрабатываете код с помощью аннотаций:

 import com.github.bedrin.jdbc.sniffer.BaseTest; import com.github.bedrin.jdbc.sniffer.Threads; import com.github.bedrin.jdbc.sniffer.Expectation; import com.github.bedrin.jdbc.sniffer.Expectations; import com.github.bedrin.jdbc.sniffer.junit.QueryCounter; import org.junit.Rule; import org.junit.Test; public class QueryCounterTest extends BaseTest { // Integrate JDBC Sniffer to your test using @Rule annotation and a QueryCounter field @Rule public final QueryCounter queryCounter = new QueryCounter(); @Test @Expectations({ @Expectation(atMost = 1, threads = Threads.CURRENT), @Expectation(atMost = 1, threads = Threads.OTHERS), }) public void testExpectations() { executeStatement(); executeStatementInOtherThread(); } }