Я узнал о подготовленных заявлениях при создании Java-приложения с поддержкой JDBC, и мое приложение использует уровень пула соединений, который заверяет меня, что подготовленные операторы кэшируются на стороне сервера, и это дает преимущество в производительности.
Тем не менее, с PHP все, что я читал, говорит, что они кэшируются только на время загрузки страницы. Обычно я не повторяю один и тот же запрос много раз, но запускаю несколько разных запросов при заданной загрузке страницы, но повторяю их при загрузке нескольких страниц.
Поскольку мои PHP-процессы являются постоянными (т. Е. Они будут обслуживать сотни страниц за всю их жизнь, а не только одну, используя PHP-FPM), мне было интересно, будут ли они повторно использовать соединения с базами данных, а не размножаться и убивать их для каждого попадания ,
Редактировать:
Чтобы уточнить, я не говорю о кеше запросов, который является еще одним зверем, или кэширует вывод запросов. Я хочу кэшировать скомпилированный подготовленный оператор и его план выполнения на стороне сервера.
Когда запрос обслуживается, php «очищает» экземпляр и освобождает ресурсы и другие переменные. Это делается в несколько этапов. Так как fastcgi сохраняет процесс в работоспособном состоянии после запроса, не все шаги выполняются, а не вся память освобождается. Существует, например, EG (persistent_list), который используется mysql_pconnect () , pg_pconnect () , … Этот список не освобождается между запросами, пока процесс сохраняется (может быть, в зависимости от фактической реализации, но это игнорировать цель EG (persistent_list)). Если вы используете постоянные соединения, ваш скрипт может получить «повторно использованное» соединение, установленное во время предыдущего запроса.
Чтобы (повторно) использовать подготовленный оператор напрямую, вам нужен идентификатор для этого оператора (и этого соединения). При использовании (php-) postgresql это просто уникальная строка (связанная с подключением) , которую вы передаете pg_execute () , поэтому ваш скрипт не имеет проблем, чтобы получить доступ к оператору, ранее подготовленному другим экземпляром (с использованием того же соединения).
Используя mysqli или PDO-mysql, вам нужен ресурс / объект как идентификатор оператора. Это проблема, поскольку ни mysqli, ни расширение pdo не предлагают способ хранения ресурса в EG (persist_list) между запросами, и вы также не можете его воссоздать. Если php-fpm не предлагает такую «услугу», представляется невозможным повторное использование подготовленного оператора mysql напрямую.
Все, на что вы можете надеяться, это серверный кеш-сервер MySQL. В последних версиях (см. Ссылку) он может распознавать инструкцию при использовании подготовленных операторов. Но даже тогда он не повторно использует фактическое подготовленное заявление:
Для подготовленного оператора, выполняемого через двоичный протокол, сравнение с операторами в кеше запросов основано на тексте заявления после расширения? маркеры параметров . Оператор сравнивается только с другими кэшированными операторами, которые выполнялись через двоичный протокол. То есть для целей кеша запросов операторы, выданные через двоичный протокол, отличаются от операторов, выданных через текстовый протокол.
Итак, если я не ошибаюсь, в настоящее время вы не можете повторно использовать оператор mysql, подготовленный во время предыдущего запроса в php.
Вы путаете то, что происходит на уровне PHP / Java, с тем, что происходит в базе данных.
Да, с использованием подготовленных операторов (обычно) означает, что план выполнения кэшируется самой базой данных (не уровень PHP / Java). Однако из этого не следует, что это всегда приводит к повышению производительности – и объяснение этого займет несколько сотен страниц. Однако я полагаю, что вы сказали в другом месте, что используете MySQL в качестве СУБД, что делает обсуждение несколько более простым (IIRC ни один из механизмов хранения не реализует гистограммы). Как правило, MySQL может кэшировать достаточную информацию о схеме, чтобы иметь возможность генерировать план без каких-либо дисковых операций ввода-вывода. OTOH, используя подготовленные инструкции, означает минимум три круглых поездки в СУБД для каждого запроса (текущий оператор, текущие параметры, получение результатов), в то время как использование встроенных значений исключает из этих круглых поездок. В отсутствие индексов гистограммы значение переменных не имеет отношения к оптимальному плану, обнаруживаемому оптимизатором.
Тот факт, что вы используете PHP, или PHP-FPM или Java с однократными или постоянными или объединенными соединениями, не имеет отношения к тому, что СУБД кэшируются или повторно используются подготовленные-заявления.
НТН
C.
Если ваше приложение PHP использует пул соединений в базе данных, а база данных кэширует подготовленные операторы, то да, кеширование будет сохраняться между страницами. Если готовое кэширование инструкции выполняется клиентской библиотекой, то это более туманно.
Вам нужно посмотреть документы для PHP-FPM и / или PDO, чтобы узнать, как сообщить им использовать пул соединений. Для этого должен быть вариант.
Вы должны знать, что установка и отключение соединения MySQL на самом деле очень быстро, и многие установки PHP не используют пул соединений из-за этого. В любом случае, вы также должны инвестировать время в настройки сервера, в частности параметр wait_timeout
. PHP также разработан вокруг идеи, что вы создаете все, что вам нужно, когда начинаются ваши страницы, и все это исчезает, когда страница заканчивается. Большинство PHP-кода и библиотек предполагают, что это так. Это совершенно другая парадигма, чем в Java.
Единственный истинный ответ – это зависит .
Подготовленные утверждения – это худые животные, когда дело доходит до MySQL. Существует множество факторов, которые определяют, кэшируется ли подготовленный оператор.
Общая идея заключается в том, что ваша версия <5.1.17, подготовленный оператор никогда не кэшируется в кеше запросов, а если используется> = 5.1.17, это зависит .
См. Следующую страницу в руководстве MySQL 5.1:
http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html
вы можете заставить mysqli создать постоянное соединение, добавив p: к имени хоста, согласно php doc: http://www.php.net/manual/en/mysqli.persistconns.php
Однако подготовленные заявления всегда закрываются между загрузками страниц, как описано здесь: http://dev.mysql.com/doc/refman/5.0/en/apis-php-mysqli.persistconns.html
Извините, это невозможно сделать, насколько я знаю. Подготовленные утверждения предназначены для загрузки одной страницы.
Подготовленные утверждения не имеют ничего общего с кэшированием результатов.
Кэширование результатов можно контролировать с помощью конфигурации сервера db или принудительно с помощью memcached и т.п.
Я предлагаю вам заглянуть в memcached , особенно для PHP http://www.php.net/manual/en/book.memcached.php
В большинстве случаев PHP не кэширует запросы и не запрашивает результаты. MySQL будет выполнять такой тип кэширования независимо от того, какой поток или соединение выдают запрос.
Если вы хотите, чтобы кеширование на стороне сервера на нескольких загрузках страниц или на нескольких серверах, используйте кеширование запросов MySQL и кеширование на стороне сервера (APC, кэширование на основе файлов, memcached и т. Д.).