Кэш подготовленных операторов с MySQL и JDBC

Я читал, что MySQL не поддерживает кеширование планов запросов на стороне сервера. Поэтому, если я хочу использовать PreparedStatements для повышения производительности, я могу включить кэширование операторов в JDBC Connection. Таким образом, согласно документации, это позволит кэшировать подготовленные операторы для каждого соединения.

Каков прирост производительности кэширования PreparedStatement с помощью соединения JDBC по сравнению с тем, если бы MySQL имел кеширование плана запроса на стороне сервера? Итак, если PreparedStatement действительно находится в кеше физического соединения, означает ли это, что когда он попадает на сервер mysql, mysql не будет запускать оптимизацию запросов на нем и сможет выполнить его напрямую?

Должен ли я вообще использовать кеширование операторов на уровне соединения JDBC при использовании MySQL в качестве базы данных? Я использую пул подключений к базе данных Hikari с соединителем Mysql JDBC.


person snegi    schedule 12.02.2014    source источник
comment
какие версии MySQL и JDBC вы используете?   -  person emecas    schedule 12.02.2014
comment
dev.mysql.com/doc/refman/5.7/en/ statement-caching.html   -  person Anthony Accioly    schedule 12.02.2014
comment
@emecas Я использую mysql-connector-java версии 5.1.18. Версия MySQL - 5.7, поскольку я намерен использовать плагин InnoDB Cache, который появился с mysql в версии mysql 5.7.   -  person snegi    schedule 12.02.2014
comment
@AnthonyAccioly: Спасибо за ссылку. Но кеширование операторов по-прежнему выполняется на основе подключения. Делает ли это что-то лучше, чем кэширование операторов на уровне JDBC?   -  person snegi    schedule 12.02.2014
comment
Вы можете сделать и то, и другое :). Кроме того, ваш пул подключений будет стоить того, чтобы кеш подключения был оправдан.   -  person Anthony Accioly    schedule 12.02.2014


Ответы (4)


Да, кеширование не повредит, если вы знаете, что делаете. Комбинация кеша на стороне клиента с кешем на стороне сервера дает преимущества в производительности, если вы повторно используете подготовленные операторы, как они должны (многие люди забывают о самой важной части: D). Просто установите свойства Connector / J свойства правильно:

cachePrepStmts=true&useServerPrepStmts=true

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

person Anthony Accioly    schedule 12.02.2014
comment
Спасибо, Энтони! Кстати, ваша ссылка для свойств Connector / J не работает - person snegi; 13.02.2014

Один из авторов HikariCP здесь. См. вики HikariCP, чтобы узнать, как правильно настроить MySQL для кэширования подготовленных операторов. Кэширование подготовленных операторов может значительно ускорить выполнение SQL. Кроме того, он может избежать атак SQL-инъекций на ваш код, которые в противном случае были бы успешными, если вы объедините вводимые пользователем данные в обычные операторы SQL. Никогда не составляйте строку SQL, содержащую вводимые пользователем данные. Всегда используйте подготовленные операторы и задавайте вводимые пользователем данные в качестве значений замены.

person brettw    schedule 13.02.2014
comment
Привет, brettw. Спасибо за прекрасный проект. Кстати, тесты против c3p0 выглядят впечатляюще. Только одно: почему вы, ребята, не рекомендуете useServerPrepStmts=true для MySQL? он также может выжать некоторую дополнительную производительность. - person Anthony Accioly; 13.02.2014
comment
Энтони, я не знал userServerPrepStmts. Добавлю в документацию, спасибо! - person brettw; 14.02.2014
comment
Некоторые простые тесты показывают, что userServerPrepStmts = false быстрее. Это также иллюстрирует ответ Влада Михалчи. - person bjmi; 25.05.2021

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

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

person O. Jones    schedule 12.02.2014

Вы можете установить два свойства:

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

Результаты производительности

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

Кэширование операторов на стороне клиента

А для операторов на стороне сервера пропускная способность также повышается за счет включения свойства cachePrepStmts:

Кэширование операторов на стороне сервера

Таким образом, механизм кэширования операторов работает и для подготовленных операторов как на стороне клиента, так и на стороне сервера.

При тестировании MySQL 8.0.22 и 8.0.18 с использованием транзакций с одним и несколькими операторами подготовленные на стороне клиента операторы работали лучше, чем подготовленные операторы на стороне сервера.

Therfeofre, следующие параметры конфигурации, кажется, дают наилучшие результаты:

useServerPrepStmts=false
cachePrepStmts=true
prepStmtCacheSize=500
prepStmtCacheSqlLimit=1024

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

person Vlad Mihalcea    schedule 07.01.2021