Автор оригинала: Vlad Mihalcea.
Во время исследования главы Кэширование операторов в моей книге Высокопроизводительная сохраняемость Java я получил возможность сравнить, как Oracle, SQL Server, PostgreSQL и MySQL обрабатывают инструкции подготовки.
Благодаря Джессу Балинту (автор драйвера MySQL JDBC), который дал замечательный ответ на StackOverflow, мне удалось лучше понять, как MySQL обрабатывает подготовленные инструкции с точки зрения производительности базы данных.
В принципе, существует два способа подготовки заявления: на стороне сервера или на стороне клиента.
Подготовленные на стороне сервера заявления
Наиболее распространенным типом является оператор на стороне сервера, который требует двух обходов базы данных:
- Драйвер отправляет запрос prepare , и база данных анализирует инструкцию в дерево запросов , которое также может быть преобразовано в предварительно оптимизированную древовидную структуру. Поскольку очень сложно построить план выполнения без фактических значений параметра привязки, план выполнения откладывается до тех пор, пока оператор не будет выполнен
- Запрос на выполнение содержит текущие значения привязки, которые база данных использует для преобразования дерева анализа в оптимальный план выполнения. Исполнитель берет план и создает соответствующий набор результатов.
Если логика доступа к данным не кэширует подготовленные инструкции, дополнительное перемещение базы данных в оба конца может фактически снизить производительность. Для этой цели некоторые системы баз данных по умолчанию не используют подготовленные операторы на стороне сервера и вместо этого выполняют подготовку операторов на стороне клиента.
Чтобы включить подготовленную инструкцию на стороне сервера, свойство useServerPrepStmts должно быть включено.
Подготовленные заявления на стороне клиента
Когда инструкция подготовлена на стороне клиента, маркеры параметров привязки заменяются фактическими значениями параметров перед отправкой инструкции на сервер базы данных. Таким образом, драйвер может использовать один запрос для получения результирующего набора.
В высокопроизводительной системе OLTP кэширование операторов играет очень важную роль в снижении задержек транзакций. Чтобы избежать многократной подготовки инструкции, драйвер MySQL предлагает кэш инструкций на стороне клиента. Будучи отключенным по умолчанию, кэш активируется свойством cachePrepStmts Подключения.
Для операторов на стороне клиента структура маркированных операторов может быть повторно использована между различными вызовами операторов подготовки. Кэш привязан к соединению с базой данных, но при использовании пула соединений время жизни физического соединения охватывает несколько транзакций на уровне приложений (поэтому часто выполняемые операторы могут извлечь выгоду из использования кэша).
Для операторов на стороне сервера драйвер кэширует ServerPreparedStatement , а также проверяет поддержку операторов на стороне сервера (не все операторы могут быть подготовлены на стороне сервера).
Инструкции кэширования могут оказать существенное влияние на производительность приложения. Если вас интересует эта тема, то вы также можете проверить высокопроизводительную сохраняемость Java, поскольку она посвящает одну главу этой конкретной теме.