Я в середине обновления / переделки кода базы данных, и мне было интересно, чего я должен ожидать от использования подготовленных операторов.
Возьмите этот пример кода:
(голый со мной, я знаю, что это уродливо – я это написал)
$values = ''; for ($i = 0; $i < $count; $i++) { $name = mysql_real_escape_string ($list[$i][1]); $voc = mysql_real_escape_string ($list[$i][3]); $lev = $list[$it][2]; $lev = is_numeric ($lev)? $lev : 0; $values .= ($values == '')? "('$name', '$voc', $lev)" : ", ('$name', '$voc', $lev)"; } if ($values != '') { $core->query ("INSERT INTO onlineCList (name, voc, lev) VALUES $values;"); }
Теперь, несмотря на очевидный выигрыш в удобочитаемости (, здравомыслие) и тот факт, что max_packet_size
перестает быть проблемой, я должен ожидать каких-либо изменений в производительности, когда я перекодирую это для использования подготовленных операторов? Я подключаюсь удаленно к серверу MySQL, и я беспокоюсь, что отправка нескольких небольших пакетов будет значительно медленнее, чем отправка одного большого пакета. Если это так, может ли MySQLi / mysqlnd кэшировать эти пакеты?
Другой пример:
$names = ''; while ($row = mysql_fetch_array ($result, MYSQL_ASSOC)) { $name = mysql_real_escape_string($row['name']); $names .= ($names == '') ? "'$name'" : ", '$name'"; } if ($names != '') { $core->query ("UPDATE onlineActivity SET online = NULL WHERE name IN ($names) AND online = 1;"); }
Как и выше, следует ли ожидать неожиданного, перекодируя это, чтобы использовать подготовленные заявления? Разве это имеет значение для сервера MySQL, если он должен запускать один запрос с большим предложением IN или несколькими подготовленными запросами с проверками равенства ( .. WHERE name = $name AND ..
)?
Предположим, что все правильно проиндексировано.
Обычно, если вы просто используете подготовленный оператор вместо простого запроса, он немного медленнее, так как запрос готов и выполняется в два шага вместо одного. Подготовленные утверждения становятся быстрее только тогда, когда вы готовите инструкцию, а затем выполняете ее несколько раз.
Однако в этом случае вы используете mysql_real_escape_string
, который выполняет mysql_real_escape_string
в базу данных. Хуже того, вы делаете это внутри цикла, поэтому выполняете его несколько раз за запрос . Таким образом, в этом случае замена всех этих roundtrips одним подготовленным заявлением является беспроигрышной.
Что касается вашего последнего вопроса, нет причин, по которым вы не можете использовать один и тот же запрос с подготовленным оператором, как и с обычным парсером запросов (т. Е. Нет причин для выполнения одной версии с IN, а другая с группой OR). Подготовленный оператор может иметь IN (?, ?, ?)
, А затем вы просто связываете это количество параметров.
Мой совет – всегда использовать подготовленные заявления. В тех случаях, когда они добавляют предельные эксплуатационные издержки, они по-прежнему стоят за безопасность (без внедрения SQL) и преимущества чтения. Конечно, в любое время, когда вы прибегаете к mysql_real_escape_string
, mysql_real_escape_string
этого вы должны использовать подготовленный оператор. (Для простых одноразовых запросов, в которых нет необходимости избегать ввода переменных, они не являются абсолютно необходимыми.)
Вы прочитаете все это!
http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html
попробуйте это тоже
Подготовленное заявление против хранимой процедуры