Готовые заявления кэшируются на стороне сервера на нескольких загрузках страниц с помощью PHP?
Я узнал о подготовленных заявлениях при создании Java-приложения с поддержкой JDBC, и мое приложение использует слой пула соединений, который гарантирует, что подготовленные операторы кэшируются на стороне сервера, и это дает преимущество в производительности.
Однако, с PHP все, что я прочитал, говорит, что они кэшируются только в течение срока службы загрузки страницы. Обычно я не повторяю один и тот же запрос много раз, но запускаю несколько разных запросов при заданной загрузке страницы, но повторяю их при загрузке нескольких страниц.
Поскольку мои PHP-процессы являются постоянными (т.е. они будут обслуживать сотни страниц за всю их жизнь, а не только одну, используя PHP-FPM), мне было интересно, будут ли они повторно использовать соединения с базами данных, а не размножаться и убивать их для каждого удара.
- Будет ли использование PHP-FPM с mysqli или PDO поддерживать соединения дольше, чем загрузка одной страницы?
- Если это не так, могу ли я это сделать?
- Если это так, или я делаю # 2, будет ли это продолжаться кеширование подготовленных операторов дольше, чем загрузка одной страницы?
Edit:
Просто, чтобы уточнить, я не говорю о кеше запросов, который является еще одним зверем, или кэширует вывод запросов. Я хочу кэшировать скомпилированный подготовленный оператор и его план выполнения на стороне сервера.
Ответы
Ответ 1
Когда запрос обслуживается, php "очищает" экземпляр и освобождает ресурсы и другие переменные. Это делается в несколько этапов. Так как fastcgi сохраняет процесс в работоспособном состоянии после запроса, не все шаги выполняются, а не вся память освобождается. Существует, например, EG (persistent_list), который используется mysql_pconnect(), pg_pconnect(),... Этот список не освобождается между запросами до тех пор, пока процесс остается в живых (может быть, в зависимости от фактической реализации, но это будет игнорировать цель EG (persistent_list)). Если вы используете постоянные подключения, ваш script может получить "повторно использованное" соединение, установленное во время предыдущего запроса.
Чтобы (повторно) использовать подготовленный оператор напрямую, вам нужен идентификатор для этого оператора (и этого соединения). При использовании (php-) postgresql это просто уникальная строка (connection-wise), которую вы передаете pg_execute(), поэтому ваш script имеет нет проблемы с получением доступа к заявлению, ранее подготовленному другим экземпляром (с использованием того же соединения).
Используя mysqli или PDO-mysql вам нужен ресурс /object как идентификатор оператора. Такая проблема, поскольку ни mysqli, ни расширение pdo не предлагают способ хранения ресурса в EG (persist_list) между запросами, и вы также не можете его воссоздать. Если php-fpm не предлагает такой "сервис", кажется невозможным повторное использование подготовленного оператора mysql напрямую.
Все, на что вы можете надеяться, это MySQL серверный кеш запросов. В последних версиях (см. Ссылку) он может распознавать инструкцию при использовании подготовленных операторов. Но даже тогда он не повторно использует фактическое подготовленное утверждение:
Для подготовленного оператора, выполняемого через двоичный протокол, сравнение с операторами в кэше запросов основывается на тексте заявления после расширения? маркеры параметров. Оператор сравнивается только с другими кэшированными операторами, которые выполнялись через двоичный протокол. То есть для целей кеша запросов операторы, выданные через двоичный протокол, отличаются от операторов, выданных через текстовый протокол.
Итак, если я не ошибаюсь, в настоящее время вы не можете повторно использовать оператор mysql, подготовленный во время предыдущего запроса в php.
Ответ 2
Вы путаете то, что происходит на уровне PHP/Java, с тем, что происходит в базе данных.
Да, используя подготовленные операторы (обычно) означает, что план выполнения кэшируется самой базой данных (НЕ - уровень PHP/Java). Однако из этого не следует, что это всегда приводит к повышению производительности - и объяснение этого займет несколько сотен страниц. Однако я полагаю, что вы сказали в другом месте, что используете MySQL в качестве СУБД, что делает обсуждение несколько более простым (IIRC ни один из механизмов хранения не реализует гистограммы). Как правило, MySQL может кэшировать достаточную информацию о схеме, чтобы иметь возможность генерировать план без каких-либо дисковых операций ввода-вывода. OTOH, используя подготовленные инструкции, означает минимум три круглых поездки в СУБД для каждого запроса (текущий оператор, текущие параметры, получение результатов), в то время как использование встроенных значений исключает из этих круглых поездок. В отсутствие индексов гистограммы значение переменных не имеет отношения к оптимальному плану, обнаруживаемому оптимизатором.
Тот факт, что вы используете PHP или PHP-FPM или Java с однократными или постоянными или объединенными соединениями, не имеет отношения к тому, что СУБД кэшируются или повторно используются подготовленные-заявления.
НТН
С.
Ответ 3
Если ваше приложение PHP использует объединение пулов в базу данных, а база данных кэширует подготовленные операторы, то да, кеширование будет сохраняться между страницами. Если кэширование подготовленного заявления выполняется клиентской библиотекой, это более туманно.
Вам нужно посмотреть документы для PHP-FPM и/или PDO, чтобы узнать, как их использовать для объединения пулов. Для этого должен быть вариант.
Вы должны знать, что установка и отключение соединения MySQL на самом деле очень быстро, и многие установки PHP не используют пул соединений из-за этого. В любом случае, вы также должны инвестировать время в настройки сервера, в частности параметр wait_timeout
. PHP также разработан вокруг идеи, что вы создаете все, что вам нужно, когда начинаются ваши страницы, и все это исчезает, когда страница заканчивается. Большинство PHP-кода и библиотек предполагают, что это так. Это совершенно другая парадигма, чем в Java.
Ответ 4
Единственный истинный ответ зависит от.
Подготовленные утверждения - это худые животные, когда дело доходит до MySQL. Существует множество факторов, которые определяют, кэшируется или нет подготовленный оператор.
Общая идея: если ваша версия < 5.1.17, подготовленный оператор никогда не кэшируется в кэше запросов, а при использовании >= 5.1.17 он зависит от.
Обратитесь к следующей странице руководства MySQL 5.1:
http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html
Ответ 5
вы можете заставить 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
Извините, это невозможно сделать, насколько я знаю. Подготовленные утверждения предназначены для загрузки одной страницы.
Ответ 6
Подготовленные утверждения не имеют ничего общего с кэшированием результатов.
Кэширование результатов можно контролировать с помощью конфигурации сервера db или принудительно с помощью memcached и т.п.
Я предлагаю вам посмотреть memcached, особенно для PHP http://www.php.net/manual/en/book.memcached.php
Ответ 7
В большинстве случаев PHP не кэширует запросы и не запрашивает результаты. MySQL будет выполнять такой тип кэширования независимо от того, какой поток или соединение выдают запрос.
Если вы хотите, чтобы кеширование на стороне сервера на нескольких загрузках страниц или на нескольких серверах, используйте кеширование запросов MySQL и кеширование на стороне сервера (APC, кэширование на основе файлов, memcached и т.д.).