2010-01-11 2 views
13

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

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

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

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

Edit:

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

ответ

12

Когда запрос подается PHP «очищает» экземпляр и освобождает ресурсы и другие переменные. Это делается в несколько этапов. Так как fastcgi сохраняет процесс в работоспособном состоянии после запроса, не все шаги выполняются, а не вся память освобождается. Существует, например, EG (persistent_list), который используется mysql_pconnect(), pg_pconnect(), ... Этот список не освобождается между запросами до тех пор, пока процесс остается в живых (может быть, в зависимости от фактической реализации, но это будет игнорировать цель EG (persistent_list)). Если вы используете постоянные соединения, ваш скрипт может получить «повторно использованное» соединение, установленное во время предыдущего запроса.
Чтобы (повторно) использовать подготовленный оператор, вам нужен идентификатор для этого оператора (и этого соединения). При использовании (php-) postgresql это просто уникальная строка (connection-wise), которую вы передаете в pg_execute(), поэтому у вашего скрипта нет проблем, чтобы получить доступ к оператору, ранее подготовленному другим экземпляром (с использованием того же соединения).
Используя mysqli или PDO-mysql, вам нужен ресурс/объект в качестве идентификатора оператора. Это проблема, поскольку ни mysqli, ни расширение pdo не предлагают способ хранения ресурса в EG (persist_list) между запросами, и вы также не можете его воссоздать. Если php-fpm не предлагает такую ​​«услугу», представляется невозможным повторное использование подготовленного оператора mysql напрямую.
Все, на что вы можете надеяться, это MySQL server-side query cache. В последних версиях (см. Ссылку) он может распознавать инструкцию при использовании подготовленных операторов. Но даже тогда он не повторно использует фактическое подготовленное заявление:

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

Итак, если я не ошибаюсь, в настоящее время вы не можете повторно использовать оператор mysql, подготовленный во время предыдущего запроса в php.

+0

Если бы я использовал postgresql, готовил бы оператор, который уже был подготовлен, автоматически доступ к ранее подготовленному заявлению или мне нужно было бы сделать магию, чтобы определить, было ли уже подготовлено утверждение? Я бы хотел отказаться от MySQL для этого. – ZoFreX

+0

Идентификатор утверждения, который вы передаете pq_prepare(), должен быть уникальным для каждого отдельного соединения. То есть если второй (или N-й) экземпляр скрипта пытается подготовить оператор снова с тем же именем, произойдет конкретная ошибка. Ваш скрипт может обработать этот код ошибки и предположить, что (правый) оператор уже подготовлен и готов к использованию. Это все еще немного накладные расходы, и вы, возможно, захотите сравнить чистый эффект, который вы можете ожидать, прежде чем вкладывать слишком много средств. – VolkerK

-1

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

Кэширование результатов можно контролировать с помощью конфигурации сервера db или принудительно с помощью memcached и т.п.

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

+0

Я ищу запрос, к которому можно получить готовые заявления. Компиляция операторов и кэширование «плана выполнения» (правильный термин, пожалуйста?) - это очень полезное пособие, которое могут дать подготовленные заявления. Я уже использую memcached для кэширования результатов, и это действительно фантастика! – ZoFreX

2

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

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

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

+0

Должен ли я использовать PDO, а не mysqli? – ZoFreX

+0

Эти два варианта предлагают несколько разные API; это не простой случай либо/или. Я лично использовал mysqli, но потом это потому, что у меня есть собственный обработчик, который расширяет mysqli так, как я хочу. – staticsan

2

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

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

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

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

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

-1

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

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

4

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

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

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

НТН

C.

+0

Примечание. PHP-FPM не работает, так как PHP работает как сервер приложений Java. Структуры пользовательских данных по-прежнему уничтожаются в конце каждого запроса. Но это все еще не имеет отношения к кэшированию высказываний. – symcbean

2

вы можете заставить MySQLi создать постоянное соединение, предваряя р: к имени хоста, в соответствии с PHP документ: http://www.php.net/manual/en/mysqli.persistconns.php

Однако подготовленные заявления всегда закрыты между страницами, как описано здесь: http://dev.mysql.com/doc/refman/5.0/en/apis-php-mysqli.persistconns.html

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

+0

Просто быть педантом ... Вам нужно добавить 'p:' not append – Basic

Смежные вопросы