Должен ли я использовать подготовленные инструкции для MySQL в PHP PERFORMANCE-WISE?

Я понимаю преимущества безопасности подготовленных операторов в MySQL. Здесь нет необходимости освещать эту тему. Мне интересно об их аспекте.

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

Однако, как насчет случая, когда я хочу только выполнить запрос один раз в одном PHP-скрипте? Казалось бы, использование подготовленного заявления хуже, потому что вы делаете две поездки на сервер, один раз для подготовки и один раз для отправки данных. Преимущество в том, что нужно только разобрать один раз, потеряно, и вы наказаны за эту вторую поездку. Если данные в бинарном формате недостаточно малы, вы теряете, используя подготовленный оператор, правильно?

Тем не менее, я прочитал некоторые противоречивые сообщения о том, что делают PHP-библиотеки mysqli или PDO? Может ли кто-нибудь из них кэшировать подготовленный оператор при выполнении скрипта? Сервер должен будет снова проанализировать подготовленный оператор на последующем pageload или нет? Если ответ отрицательный, что утверждение не нужно анализировать во второй pageload, тогда казалось бы, что подготовленные операторы лучше, даже если вы выполняете запрос только один раз за pageload.

Пожалуйста, примите во внимание, если что-то изменилось между версиями MySQL относительно этого. Вы можете смело предположить, что я использую PHP 5.2

EDIT: просто для того, чтобы яснить, мне нужен ответ для MySQL и PHP, в частности, с указанием версии MySQL и, если это было когда-то иначе, и ТОЛЬКО рассматривать производительность, а не простоту использования или безопасности.

ОБНОВЛЕНИЕ: Я принял ответ, который я сделал, потому что в комментарии к последующим комментариям было несколько хороших идей. Я все еще немного разочарован тем, что никто, кажется, не может ответить на вопрос, который я задал с какой-либо определенностью. Я думаю, иногда ответ действительно «зависит».

История

Это был мой первый ответ Stackoverflow. С тех пор многое изменилось, особенно из-за устаревания и удаления API-интерфейса mysql. Даже если вы все еще на php 5.6, mysql_ * api не следует использовать. Теперь PDO или mysqli являются единственными вариантами выбора. PDO лучше по многим причинам.

Готовые заявления кэшируются через загруженные страницы?

Я прочитал некоторые противоречивые сообщения о том, что делают библиотеки MySQL или PDO PHP? Может ли кто-нибудь из них кэшировать подготовленный оператор при выполнении скрипта?

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

Для больших вставок (в тысячах строк) Увеличение вероятности может быть достигнуто путем сброса ваших данных в текстовый файл и загрузки его с помощью LOAD DATA IN FILE. Это намного быстрее, чем серия вставок.

Оригинальный ответ

Правда в том, что иногда mysqli работает быстрее, а в других случаях mysql api быстрее. Но разница действительно очень маленькая. Если вы посмотрите на какие-либо тесты производительности в Интернете, разница действительно составляет всего 10-20 миллисекунд. Лучший способ повысить производительность – это оптимизировать дизайн таблицы.

Многие тесты, которые «доказывают» более старый api быстрее, забывают, что для максимальной безопасности mysql_real_escape_string () следует вызывать для каждой переменной, используемой в запросе.

Запросы кэшируются сервером, если и только если данные во всех таблицах, которые используются в запросе, остались неизменными.

Ожидание другого обновления с фактическими номерами

«Использование подготовленных заявлений никогда не является плохой идеей»

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

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

 SELECT name, address, phone from tbl WHERE id = ? 

и у вас есть другой идентификатор для каждого вызова. Таким образом, стоит потратить дополнительное путешествие в дБ для подготовки, потому что вы, вероятно, назовете его сотни или тысячи раз и просто измените параметр. Но вы ожидаете удалить подготовленный оператор из кеша или закрыть соединение в конце, скажем, вашего сценария без состояния (php, perl, jsp, ruby ​​и т. Д.).
Если вы не удаляете подготовленный оператор и используете пул соединений, вы обязаны заполнить кеш с течением времени и получить неприятную ошибку «Невозможно создать более чем max_prepared_stmt_count заявления». Я говорю по опыту, поэтому подумайте о том, действительно ли вам нужны подготовленные заявления, потому что вы точно знаете, что повторяете один и тот же параметризованный запрос снова и снова в замкнутом цикле.
Если нет, то, что вы, вероятно, ищете, позволяет mysql использовать свой основной кеш запросов, который является другим механизмом, чем подготовленный список операторов, и который ведет себя как настоящий LRU-кеш из моего понимания.

Использование подготовленных заявлений никогда не является плохой идеей. Я недавно не использовал их с mySQL, но я использовал их с SQLSERVER, и они отлично работают.

Библиотека PDO, вероятно, не выполняет никакого кэширования, но база данных будет подготовлена ​​для подготовленного оператора.

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

Что именно вы имеете в виду «разбираетесь во второй pageload»?

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

Теперь я не могу спорить о подготовке + выполнить против простого запроса, производительности (без повторных запросов);

Но чтобы сохранить mysql при анализе сложного запроса при каждом выполнении одного скрипта, вы должны использовать хранимые процедуры; запрос должен быть только CALL items(date,search_etc,id); вместо SELECT i.id FROM products as p JOIN item_prodct as t ON... JOIN items as i... ON... WHERE ... p.date ... i.search_etc ...

Вы можете использовать хранимые процедуры с подготовленными операторами.

Не для всех случаев. Бывают случаи, когда подготовленные операторы выполняются медленнее, чем запрошенный вручную запрос, даже если он выполняется повторно .

Например, когда мне нужно вставить сотни строк в одну загрузку страницы, я нахожу:

 $pdo -> query("INSERT INTO table (field1, field2, ...) VALUES (".$pdo -> quote($value1).", ".$pdo -> quote($value2).", ...), (row2), (row3), ..., (row100), ..."); 

МНОГО быстрее, чем:

 $stmt = $pdo -> prepare("INSERT INTO table (field1, field2, ...) VALUES (:value1, :value2, ...)"); foreach (/* some hundred times */) { $stmt -> execute(array('value1' => $value1, 'value2' => $value2, ...)); }