Автор оригинала: Vlad Mihalcea.
Вступление
Хотя разработка приложения Spring Boot довольно проста, настройка производительности приложения Spring Boot является более сложной задачей, поскольку для этого требуется не только понять, как работает платформа Spring за кулисами, но и знать, как лучше всего использовать базовую платформу доступа к данным, например, Hibernate.
В предыдущей статье я показал вам , как легко оптимизировать производительность демонстрационного приложения Petclinic. Однако по умолчанию приложение Petclinic Spring Boot использует базу данных HSQLDB в памяти, для которой вы обычно не хотите, чтобы ваше приложение было оптимизировано.
В этой статье мы собираемся переключить базовую базу данных с HSQLDB в памяти на MySQL и запустить оптимизатор гиперсистенции для создания отчета о настройке производительности для JPA и гибернации уровня доступа к данным в контексте базы данных MySQL.
Настройка производительности приложения #SpringBoot может быть сложной задачей. @vlad_mihalcea показывает вам #как создать отчет о настройке производительности для #JPA и Гибернировать уровень доступа к данным в контексте #MySQL базы данных.
Весенняя Петклиника
Spring Petclinic – это демонстрационное приложение, созданное с использованием Spring Boot, которое демонстрирует возможности платформы.
По умолчанию Spring Boot использует HSQLDB, но, хотя эта база данных в памяти широко используется для тестирования, в производственной среде вы, скорее всего, будете использовать базу данных, такую как MySQL или PostgreSQL.
К счастью, Spring Boot предлагает конфигурацию MySQL и профиль Spring, которые мы можем использовать в качестве отправной точки для нашего анализа.
Переключение тестов на использование профиля MySQL
Прежде всего, нам нужно использовать аннотацию @ActiveProfiles
для активации mysql
Профиль пружины.
@RunWith(SpringRunner.class) @SpringBootTest @ActiveProfiles("mysql") public class PetclinicIntegrationTests { @Autowired private VetRepository vets; @Test public void testFindAll() throws Exception { vets.findAll(); vets.findAll(); // served from cache } }
После активации mysql
Профиль Spring, загрузка Spring будет использовать файл конфигурации application-mysql.properties
для переопределения параметров из файла настроек по умолчанию application.properties
.
В нашем случае единственным изменением, которое требовалось внести в файл конфигурации application-mysql.properties
, было изменение учетных данных подключения к базе данных:
database=mysql spring.datasource.url=jdbc:mysql://localhost/petclinic spring.datasource.username=mysql spring.datasource.password=admin
Запуск оптимизатора сохраняемости Hy
Как вы можете видеть в классе Интеграционные тесты клиники домашних животных
, запустить оптимизатор гиперситуации очень просто, так как вам просто нужно пройти EntityManagerFactory
экземпляр в гиперсистенци-оптимизатор
конструктор объектов и вызов метода init
.
Hypersistence Optimizer : CRITICAL - TableGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.owner.Pet] entity uses the TABLE strategy, which does not scale very well. Consider using the IDENTITY identifier strategy instead, even if it does not allow JDBC batch inserts. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#TableGeneratorEvent Hypersistence Optimizer : CRITICAL - TableGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.owner.Owner] entity uses the TABLE strategy, which does not scale very well. Consider using the IDENTITY identifier strategy instead, even if it does not allow JDBC batch inserts. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#TableGeneratorEvent Hypersistence Optimizer : CRITICAL - TableGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.visit.Visit] entity uses the TABLE strategy, which does not scale very well. Consider using the IDENTITY identifier strategy instead, even if it does not allow JDBC batch inserts. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#TableGeneratorEvent Hypersistence Optimizer : CRITICAL - TableGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.owner.PetType] entity uses the TABLE strategy, which does not scale very well. Consider using the IDENTITY identifier strategy instead, even if it does not allow JDBC batch inserts. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#TableGeneratorEvent Hypersistence Optimizer : CRITICAL - TableGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.vet.Specialty] entity uses the TABLE strategy, which does not scale very well. Consider using the IDENTITY identifier strategy instead, even if it does not allow JDBC batch inserts. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#TableGeneratorEvent Hypersistence Optimizer : CRITICAL - TableGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.vet.Vet] entity uses the TABLE strategy, which does not scale very well. Consider using the IDENTITY identifier strategy instead, even if it does not allow JDBC batch inserts. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#TableGeneratorEvent Hypersistence Optimizer : MAJOR - DialectVersionEvent - Your application is using the [org.hibernate.dialect.MySQL5Dialect] Hibernate-specific Dialect. Consider using the [org.hibernate.dialect.MySQL57Dialect] instead as it's closer to your current database server version [MySQL 8.0]. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#DialectVersionEvent
Событие Генератора таблиц
Событие Генератор таблиц запускается, потому что в предыдущей статье мы переключили стратегию идентификатора сущности с ИДЕНТИЧНОСТИ
на ПОСЛЕДОВАТЕЛЬНОСТЬ
.
Использование стратегии ПОСЛЕДОВАТЕЛЬНОСТИ идентификаторов является лучшим вариантом, если и только если базовая база данных поддерживает объекты последовательности. Однако MySQL 8 не поддерживает последовательности баз данных, и по этой причине Hibernate переключается на использование генератора ТАБЛИЦ
, и, как объясняется в его статье , генератор ТАБЛИЦ
является ужасным выбором , когда дело доходит до производительности приложений.
Переход на использование идентификатора для MySQL
Таким образом, в нашем случае нам лучше использовать генератор IDENTITY
для MySQL. Однако мы не хотим изменять сопоставления сущностей на IDENTITY
, поскольку нам может потребоваться развернуть приложение Petclinic в других системах баз данных, таких как Oracle, SQL Server или PostgreSQL, которые поддерживают последовательности баз данных. Итак, мы хотим, чтобы сопоставление по умолчанию использовало стратегию SEQUENCE
, но изменило ее только на IDENTITY
для MySQL.
Даже если генератор IDENTITY
не позволяет Hibernate паковать инструкции INSERT на уровне JDBC, все равно лучше использовать эту стратегию, а не генератор TABLE
. Для получения более подробной информации о пакетных обновлениях JDBC ознакомьтесь с этой статьей .
И решение на самом деле очень простое. На самом деле, я уже объяснял это в этой статье .
Путем предоставления специфичного для MySQL orm.xml
Файл конфигурации JPA, который переопределяет стратегию идентификатора сущности базового класса, мы можем переключиться на использование IDENTITY
при использовании MySQL.
Итак, мы собираемся создать orm.xml
файл, который будет развернут профилем mysql
в папке META-INF
в файле приложения jar
.
В orm.xml
файл конфигурации выглядит следующим образом:
Вот и все!
Теперь при повторном запуске интеграционных тестов Pet clinic
тестового случая оптимизатор Гиперсистенции создаст следующий отчет:
Hypersistence Optimizer : MINOR - IdentityGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.owner.Pet] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Since the database does not support the SEQUENCE identifier strategy, you need to use plain JDBC or some other data access framework to batch insert statements. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent Hypersistence Optimizer : MINOR - IdentityGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.owner.Owner] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Since the database does not support the SEQUENCE identifier strategy, you need to use plain JDBC or some other data access framework to batch insert statements. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent Hypersistence Optimizer : MINOR - IdentityGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.visit.Visit] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Since the database does not support the SEQUENCE identifier strategy, you need to use plain JDBC or some other data access framework to batch insert statements. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent Hypersistence Optimizer : MINOR - IdentityGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.owner.PetType] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Since the database does not support the SEQUENCE identifier strategy, you need to use plain JDBC or some other data access framework to batch insert statements. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent Hypersistence Optimizer : MINOR - IdentityGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.vet.Specialty] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Since the database does not support the SEQUENCE identifier strategy, you need to use plain JDBC or some other data access framework to batch insert statements. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent Hypersistence Optimizer : MINOR - IdentityGeneratorEvent - The [id] identifier attribute in the [org.springframework.samples.petclinic.vet.Vet] entity uses the [IdentityGenerator] strategy, which prevents Hibernate from enabling JDBC batch inserts. Since the database does not support the SEQUENCE identifier strategy, you need to use plain JDBC or some other data access framework to batch insert statements. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#IdentityGeneratorEvent Hypersistence Optimizer : MAJOR - DialectVersionEvent - Your application is using the [org.hibernate.dialect.MySQL5Dialect] Hibernate-specific Dialect. Consider using the [org.hibernate.dialect.MySQL57Dialect] instead as it's closer to your current database server version [MySQL 8.0]. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#DialectVersionEvent
Обратите внимание, что событие Генератор таблиц
было заменено Генератором идентификаторов
. Генератор идентификаторов генерируется, потому что стратегия IDENTITY
не позволяет Hibernate выполнять пакетные инструкции INSERT при вызове persist
поскольку ему необходимо знать идентификатор сущности при связывании сохраняющейся сущности с кэшем первого уровня.
Но поскольку у нас на самом деле нет опции для Генератора идентификаторов
при использовании MySQL, мы можем просто проигнорировать это событие в нашем случае.
Фильтрация событий оптимизатора Гиперстабильности
Оптимизатор гиперсиленса очень гибкий. Вы можете настроить, как обрабатываются события , хотите ли вы, чтобы они регистрировались или собирались в Список
, а также можете выбрать фильтрацию событий.
Чтобы отфильтровать событие Генератор идентификационных данных
, вам необходимо настроить Гиперстистенционный оптимизатор
компонент следующим образом:
@Configuration public class HypersistenceConfiguration { @Bean public HypersistenceOptimizer hypersistenceOptimizer( EntityManagerFactory entityManagerFactory) { return new HypersistenceOptimizer( new JpaConfig(entityManagerFactory) .setEventFilter( event -> !(event instanceof IdentityGeneratorEvent) ) ); } }
Теперь при повторном запуске интеграционных тестов Pet clinic
тестового случая оптимизатор гиперсуществования предотвратит включение в отчет события identitygenerator/|:
Hypersistence Optimizer : MAJOR - DialectVersionEvent - Your application is using the [org.hibernate.dialect.MySQL5Dialect] Hibernate-specific Dialect. Consider using the [org.hibernate.dialect.MySQL57Dialect] instead as it's closer to your current database server version [MySQL 8.0]. For more info about this event, check out this User Guide link - https://vladmihalcea.com/hypersistence-optimizer/docs/user-guide/#DialectVersionEvent
Событие Диалектной версии
Событие Версия диалекта генерируется, потому что по умолчанию настроен диалект гибернации MySQL57Dialect
в то время как приложение Petclinic работает против MySQL 8.
Итак, нам просто нужно включить Диалект MySQL 8
в файл конфигурации Spring Boot application-mysql.properties
:
database=mysql spring.datasource.url=jdbc:mysql://localhost/petclinic spring.datasource.username=mysql spring.datasource.password=admin spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL8Dialect
И теперь оптимизатор персистентности Hy не сообщает о каких-либо проблемах. Круто, правда?
Вывод
Оптимизатор гиперсистенции-это очень мощный инструмент, который может помочь вам обнаружить проблемы с производительностью JPA и гибернации задолго до того, как они возникнут в производственной системе.
И одним из его самых больших преимуществ является то, что он может выполнять все эти проверки при каждой фиксации, так что вы больше не будете упускать из виду повышение производительности JPA или гибернации из-за очень плотного графика разработки.
Все оптимизации, представленные в этой статье, можно найти в этом репозитории GitHub .