Подтвердить что ты не робот

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

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

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

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

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

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

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

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

4b9b3361

Ответ 1

История

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

Готовые заявления, кэшированные на разных страницах?

Я прочитал некоторые противоречивые сообщения о том, что PHP mysqli или PDO библиотеки? Сделайте ли каждый из них кэширование подготовленного заявления через script выполнение?

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

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

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

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

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

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

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

Ответ 2

"Использование подготовленных операторов никогда не является плохим решением"

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

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

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

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

Ответ 3

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

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

$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, ...));
}

ОБНОВИТЬ

Я написал этот ответ 4 года назад, с тех пор я узнал что-то новое об этом.

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

Однако я никогда не проверял, что является более быстрой, неподготовленной INSERT для одной партии с 1000 строками или 1000 выполнений подготовленной INSERT, заключенной в транзакцию.

Ответ 4

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

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

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

Ответ 5

Что именно вы имеете в виду "разбирается во второй pageload"?

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

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

Но, чтобы сохранить mysql при анализе сложного запроса в каждом выполнении script, вы должны использовать хранимые процедуры; запрос был бы просто 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 ...

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

Ответ 6

подготовленное выражение

Подготовленные операторы могут быть более безопасными, чем выполнение запросов по старинке, но они также могут быть быстрее. Если PHP-скрипт отправляет один и тот же запрос в MySQL несколько раз, каждый раз используя разные значения, подготовленные операторы действительно могут ускорить процесс. В таких случаях сам запрос отправляется только в MySQL и анализируется один раз. Затем значения отправляются в MySQL отдельно. В качестве тривиального примера следующий код будет выполнять 100 запросов в MySQL:

$q = 'INSERT INTO counter (num) VALUES (?)';
$stmt = mysqli_prepare($dbc, $q);
mysqli_stmt_bind_param($stmt, 'i', $n);
for ($n = 1; $n <= 100; $n++) {
mysqli_stmt_execute($stmt);
}

Несмотря на то, что запрос выполняется 100 раз, полный текст передается и анализируется MySQL только один раз. Версии MySQL 5.1.17 и более поздние включают механизм кэширования, который также может улучшить производительность других видов использования подготовленных операторов. Когда не используются подготовленные операторы, весь запрос, включая синтаксис SQL и конкретные значения, отправляется в MySQL в виде одной длинной строки. Затем MySQL анализирует и выполняет его. С подготовленным запросом синтаксис SQL сначала отправляется в MySQL, где он анализируется, проверяя его синтаксически допустимость (например, подтверждая, что запрос не ссылается на таблицы или столбцы, которые не существуют). Затем конкретные значения отправляются отдельно; MySQL собирает запрос, используя эти значения, а затем выполняет его. Важны преимущества готовых заявлений: повышение безопасности и потенциально лучшая производительность. Я сконцентрируюсь на аспекте безопасности здесь, но на боковой панели для обсуждения производительности.

Ссылка: книга Ларри Уллмана (PHP и MySQL для динамических веб-сайтов)