Как сделать подготовленное заявление для 1000 различных запросов, которые будут разделены между потоками? - PullRequest
0 голосов
/ 07 декабря 2018

В настоящее время у нас есть около 1000 запросов, которые выполняются (по мере необходимости, т. Е. Все 1000 не выполняются одновременно, но некоторые конкретные 20 выполняются с высокой скоростью) как часть процедуры порожденными исполнителями задач, проходящими черезВ некоторых блогах я оценил использование PreparedStatement, но в настоящее время мы не используем его.Было бы целесообразно переключиться на подготовленные операторы при использовании dbcp2 в качестве пула соединений?

1 Ответ

0 голосов
/ 08 декабря 2018

Я оценил использование PreparedStatement, но в настоящее время мы не используем его.

Типичное использование: (1) подготовка заявлениязатем (2) используйте его один или несколько раз в единственном потоке .Это может быть быстрее, чем обычное утверждение, даже если вы используете его только один раз.Так что обязательно попробуйте.

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

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

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

Учтите, что на уровне пула у пула нет другого выбора, кроме как кэшировать объекты JDBC PreparedStatement для каждого соединения.Если пользователь говорит, что хочет кэшировать 250 подготовленных операторов, а в пуле 50 соединений, это 12500 объектов.Или 50000 объектов, с 500 операторами и 100 связями.И это даже не считая таких вещей, как записи HashMap.

Теперь возьмем PostgreSQL в качестве контрпримера.PostgreSQL реализует подготовленные операторы с помощью так называемых «именованных запросов».Когда вы готовите заявление, ему дается имя.Именованные запросы хранятся на стороне сервера вместе с соответствующим планом выполнения.Именованные запросы являются глобальными и совместно используются соединениями.Драйвер хранит сопоставление строк SQL с именами запросов.

Итак, когда вы вызываете Connection.prepareStatement(), драйвер проверяет, существует ли именованный запрос для данного SQL.Если это так, он создает новый объект PreparedStatement, который ссылается на запрос по имени на стороне сервера.

Нет PreparedStatement объекты хранятся в памяти или кэшируются.И это работает, даже если исходное Соединение, которое использовалось для подготовки оператора, было закрыто или подготовка была выполнена для другого Соединения.

Это уровень эффективности и производительности, которому пул не может соответствовать.

Я бы сказал, что предоставление кэша выписок скорее повредит пользователям других баз данных, чем поможет.Я могу сказать это с некоторой уверенностью, потому что большое количество пользователей, переключающихся с BoneCP или DBCP на HikariCP, спрашивают: «Где кэш операторов ?!»Даже не зная, что это было поддержано по своей сути их водителем.Лучше.

Например, при использовании MySQL, кеширование PreparedStatement может быть включено в самом драйвере следующим образом:

HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/dbname");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
HikariDataSource ds = new HikariDataSource(config);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...