Рубрики
Без рубрики

14 Советов по сохранению высокой Производительности Java

Изучите различные высокопроизводительные советы по оптимизации сохраняемости Java, которые помогут вам получить максимальную отдачу от уровня доступа к данным.

Автор оригинала: Vlad Mihalcea.

Вступление

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

Высокопроизводительный уровень доступа к данным требует больших знаний о внутренних компонентах базы данных, JDBC, JPA, Hibernate, и в этом посте кратко излагаются некоторые из наиболее важных методов, которые вы можете использовать для оптимизации своего корпоративного приложения.

1. Ведение журнала инструкций SQL

Если вы используете платформу, которая генерирует инструкции от вашего имени, вы всегда должны проверять эффективность и действенность каждой выполняемой инструкции . Механизм утверждения во время тестирования еще лучше, потому что вы можете обнаружить N+1 проблем с запросами еще до того, как вы зафиксируете свой код.

2. Управление подключением

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

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

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

3. Пакетирование JDBC

Пакетирование JDBC позволяет нам отправлять несколько операторов SQL в одну базу данных в оба конца. Прирост производительности значителен как со стороны драйвера, так и со стороны базы данных. Подготовленные заявления являются очень хорошими кандидатами для пакетной обработки, и некоторые системы баз данных (например, Oracle) поддерживают пакетную обработку только для подготовленных заявлений.

Поскольку JDBC определяет отдельный API для пакетной обработки (например, PreparedStatement.addBatch и PreparedStatement.executeBatch ), если вы создаете инструкции вручную, вы должны с самого начала знать, следует ли использовать пакетную обработку или нет. С помощью режима гибернации вы можете переключиться на пакетирование с помощью одной конфигурации .

Hibernate 5.2 предлагает пакетирование на уровне сеанса , поэтому он еще более гибок в этом отношении.

4. Кэширование инструкций

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

5. Идентификаторы гибернации

При использовании режима гибернации генератор IDENTITY не является хорошим выбором, так как он отключает пакетирование JDBC.

Генератор ТАБЛИЦ еще хуже, так как он использует отдельную транзакцию для получения нового идентификатора, что может оказать давление на базовый журнал транзакций, а также на пул соединений, поскольку каждое новое соединение требуется каждый раз, когда нам нужен новый идентификатор.

ПОСЛЕДОВАТЕЛЬНОСТЬ является правильным выбором, и даже SQL Server поддерживает начиная с версии 2012. Для идентификаторов ПОСЛЕДОВАТЕЛЬНОСТИ Hibernate уже давно предлагает оптимизаторы, такие как объединенный или объединенный-lo , которые могут уменьшить количество обходов базы данных, необходимых для получения нового значения идентификатора сущности.

6. Выбор правильных типов столбцов

Вы всегда должны использовать правильные типы столбцов на стороне базы данных. Чем компактнее тип столбца, тем больше записей можно разместить в рабочем наборе базы данных, а индексы будут лучше помещаться в память. Для этой цели вам следует воспользоваться преимуществами типов, специфичных для базы данных (например, inet для IPv4-адресов в PostgreSQL), тем более что Hibernate очень гибок, когда дело доходит до реализации нового пользовательского типа .

7. Взаимоотношения

Hibernate поставляется со многими типами сопоставления отношений, но не все они одинаковы с точки зрения эффективности.

Следует избегать однонаправленных коллекций и @ManyToMany Списков (списков). Если вам действительно нужно использовать коллекции сущностей, то предпочтительны двунаправленные @OneToMany ассоциации. Для отношения @ManyToMany используйте набор(ы), так как в этом случае они более эффективны или просто сопоставьте также связанную таблицу “многие ко многим” и превратите отношение @ManyToMany в две двунаправленные @OneToMany ассоциации.

Однако, в отличие от запросов, коллекции менее гибки, поскольку их нелегко разбить на страницы, а это означает, что мы не можем использовать их, когда число дочерних ассоциаций довольно велико. По этой причине вы всегда должны задаваться вопросом, действительно ли необходима коллекция. Запрос сущности может быть лучшей альтернативой во многих ситуациях.

8. Наследование

Когда дело доходит до наследования, несоответствие импеданса между объектно-ориентированными языками и реляционными базами данных становится еще более очевидным. JPA предлагает SINGLE_TABLE , JOINED и TABLE_PER_CLASS для работы с отображением наследования , и у каждой из этих стратегий есть плюсы и минусы.

SINGLE_TABLE работает лучше всего с точки зрения операторов SQL , но мы теряем целостность данных, так как не можем использовать ограничения NOT NULL .

JOINED устраняет ограничение целостности данных, предлагая более сложные инструкции. До тех пор, пока вы не используете полиморфные запросы или @OneToMany ассоциации с базовыми типами, эта стратегия подойдет. Его истинная сила исходит от полиморфных @ManyToOne ассоциаций, подкрепленных стратегическим шаблоном на стороне уровня доступа к данным.

TABLE_PER_CLASS следует избегать, так как он не отображает эффективные операторы SQL.

9. Размер контекста сохранения

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

10. Получение только того, что необходимо

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

ЧТОБЫ проекции лучше подходили для извлечения пользовательских представлений , в то время как объекты следует извлекать только тогда, когда бизнес-поток требует их изменения.

НЕТЕРПЕЛИВАЯ выборка-это худшее , и вам следует избегать анти-шаблонов, таких как просмотр открытой сессии .

11. Кэширование

Системы реляционных баз данных используют множество буферных структур в памяти, чтобы избежать доступа к диску . Кэширование базы данных очень часто упускается из виду . Мы можем значительно сократить время отклика, правильно настроив компонент database engine таким образом, чтобы рабочий набор находился в памяти и не извлекался все время с диска.

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

Кэш второго уровня очень полезен для сокращения времени отклика на транзакции чтения-записи, особенно в архитектурах с одной первичной репликацией. В зависимости от требований приложения, Hibernate позволяет выбирать между READ_ONLY , NONSTRICT_READ_WRITE , READ_WRITE и ТРАНЗАКЦИОННЫМ .

12. Контроль параллелизма

Выбор уровня изоляции транзакций имеет первостепенное значение, когда речь заходит о производительности и целостности данных. Для веб-потоков с несколькими запросами, чтобы избежать потери обновлений , следует использовать оптимистичную блокировку с отдельными объектами или РАСШИРЕННЫЙ контекст сохранения .

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

13. Раскройте возможности запросов к базе данных

Просто потому, что вы используете JPA или спящий режим, это не значит, что вы не должны использовать собственные запросы. Вы должны воспользоваться Оконными функциями , CTE (Общие табличные выражения), ПОДКЛЮЧАТЬСЯ , СВОДИТЬ .

Эти конструкции позволяют избежать извлечения слишком большого количества данных только для их последующего преобразования на прикладном уровне. Если вы позволите базе данных выполнять обработку, вы сможете получить только конечный результат, что позволит сэкономить много дисковых операций ввода-вывода и сетевых затрат. Чтобы избежать перегрузки главного узла, можно использовать репликацию базы данных и иметь несколько доступных узлов-реплик, чтобы задачи, требующие больших объемов данных, выполнялись на реплике, а не на Главном.

14. Увеличивайте и уменьшайте масштаб

Реляционные базы данных очень хорошо масштабируются. Если Facebook , Twitter , Pinterest или StackOverflow могут масштабировать свою систему баз данных, есть большая вероятность, что вы сможете масштабировать корпоративное приложение в соответствии с его конкретными бизнес-требованиями.

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

Вывод

Высокопроизводительный уровень доступа к данным должен соответствовать базовой системе баз данных. Знание внутренней работы реляционной базы данных и используемых структур доступа к данным может сделать разницу между высокопроизводительным корпоративным приложением и приложением, которое едва просматривается.

Есть много вещей, которые вы можете сделать, чтобы повысить производительность вашего уровня доступа к данным, и я здесь только царапаю поверхность. Если вы хотите прочитать больше по этой конкретной теме, вам также следует ознакомиться с моей книгой о сохранении высокой производительности Java. Эта книга, содержащая более 450 страниц, очень подробно объясняет все эти концепции.