Готовые операторы кэшируются на стороне сервера при загрузке нескольких страниц с помощью PHP? - PullRequest
14 голосов
/ 11 января 2010

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

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

Поскольку мои процессы PHP являются постоянными (т.е. они будут обслуживать сотни страниц за время жизни вместо одной, используя PHP-FPM), мне было интересно, будут ли они повторно использовать соединения с базой данных, а не порождать и убивать их за каждый удар.

  1. Будет ли использование PHP-FPM с mysqli или PDO поддерживать соединения дольше, чем загрузка одной страницы?
  2. Если нет, могу ли я это сделать?
  3. Если это произойдет, или я сделаю № 2, будет ли сохраняться кэширование подготовленных операторов дольше, чем загрузка одной страницы?

Edit:

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

Ответы [ 7 ]

12 голосов
/ 11 января 2010

Когда запрос обслужен, 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.

4 голосов
/ 01 февраля 2010

Вы путаете то, что происходит на уровне PHP / Java, с тем, что происходит в базе данных.

Да, использование подготовленных операторов (обычно) означает, что план выполнения кэшируется самой базой данных (НЕ уровнем PHP / Java). Однако из этого не следует, что это всегда приводит к лучшей производительности - и объяснение этого заняло бы несколько сотен страниц. Однако из того, что вы сказали в другом месте, вы используете MySQL в качестве СУБД, что делает обсуждение несколько проще (IIRC ни один из механизмов хранения не реализует гистограммы). Как правило, MySQL сможет кэшировать достаточно информации о схеме, чтобы можно было сгенерировать план без дискового ввода-вывода. OTOH, использование подготовленных операторов означает минимум три обращения к СУБД для каждого запроса (представление оператора, представление параметров, получение результатов), а использование встроенных значений исключает одно из этих обращений. В отсутствие индексов гистограммы значение переменных не имеет отношения к оптимальному плану, определяемому оптимизатором.

Тот факт, что вы используете PHP, или PHP-FPM, или Java с одиночными, постоянными или объединенными в пул соединениями, не имеет отношения к тому, кэшируются / повторно используются подготовленные операторы СУБД.

НТН

С

2 голосов
/ 02 февраля 2010

вы можете заставить 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

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

2 голосов
/ 11 января 2010

Единственный верный ответ: это зависит .

Подготовленные операторы - привередливые звери, когда дело доходит до MySQL. Существует множество факторов, которые определяют, кэшируется ли подготовленный оператор.

Общая идея заключается в том, что если ваша версия <5.1.17, подготовленный оператор <em>никогда не кэшируется в кеше запросов, а при использовании> = 5.1.17, это зависит .

Пожалуйста, смотрите следующую страницу в руководстве MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/en/query-cache-operation.html

2 голосов
/ 11 января 2010

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

Вам нужно посмотреть документы для PHP-FPM и / или PDO, чтобы узнать, как сказать им использовать пул соединений. В обоих случаях должен быть вариант.

Вы должны знать, что установка и разрыв соединения MySQL на самом деле очень быстрая, и многие установки PHP не используют пул соединений из-за этого. В любом случае, вам также следует потратить время на настройку сервера, в частности на параметр wait_timeout. PHP также основан на идее, что вы создаете все, что вам нужно, когда ваши страницы запускаются, и все это исчезает, когда страница заканчивается. Большинство PHP-кода и библиотек предполагают, что это так. Это совсем другая парадигма, чем в Java.

0 голосов
/ 11 января 2010

PHP в большинстве случаев не кэширует запросы и не запрашивает результаты. MySQL будет выполнять этот вид кэширования независимо от того, какой поток или соединение выдает запрос.

Если вы хотите кэширование на стороне сервера для нескольких загрузок страниц или нескольких серверов, используйте кэширование запросов MySQL и кэширование на стороне сервера (APC, файловое кэширование, memcached и т. Д.).

0 голосов
/ 11 января 2010

Подготовленные операторы не имеют ничего общего с кэшированием результатов.

Кэшированием результатов можно управлять через конфигурацию сервера БД или принудительно через memcached и т. П.

Предлагаю вам посмотреть memcached , особенно для PHP http://www.php.net/manual/en/book.memcached.php

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...