MySQL准备语句与普通查询.收益与损失

Opi*_*piF 3 php mysql web-services

我在更新/返工一些数据库代码,我在想,我应该中间真正使用预处理语句的期望.

拿这个例子代码:(
裸露在我身边,我知道它很难看 - 我写的)

$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;");
}
Run Code Online (Sandbox Code Playgroud)

现在,除了可读性(理智性)明显增加以及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;");
}
Run Code Online (Sandbox Code Playgroud)

如上所述,我应该在重新编码后使用准备好的语句吗?它是否对MySQL服务器有任何影响,如果它必须运行一个带有大IN子句的查询,或者多个准备好的查询带有相等性检查(.. WHERE name = $name AND ..)?

假设所有内容都已正确编入索引.

joe*_*rdi 11

通常,如果您只使用预准备语句代替普通查询,那么它会稍微慢一些,因为查询是以两步而不是一步编写和执行的.只有在准备语句然后多次执行时,准备好的语句才会变得更快.

但是,在这种情况下,您正在使用mysql_real_escape_string,它会对数据库进行往返.更糟糕的是,你是在一个循环中进行的,因此,每次查询多次执行它.因此,在这种情况下,用一个准备好的声明替换所有这些往返是一种双赢.

关于你的上一个问题,没有理由你不能像使用正常的查询解析器那样使用与预准备语句相同的查询(即没有理由用IN执行一个版本而另一个用一堆OR执行).将准备好的语句可以有IN (?, ?, ?),然后你只绑定这个数字的参数.

我的建议是始终使用准备好的陈述.如果它们增加了边际性能开销,那么它们仍然值得为安全性(无SQL注入)和可读性带来好处.当然,无论何时你发现自己mysql_real_escape_string都在使用,你应该使用准备好的声明.(对于简单的一次性查询,不需要转换变量输入,它们不是绝对必要的.)

  • 是的,它应该在PHP文档中更突出,它做到了.字节流被发送到MySQL,它使用其字符集设置转义并返回转义字符串...如果打开MySQL服务器的查询日志,您将看到所有这些"查询".有一个旧的[mysql_escape_string](http://php.net/manual/en/function.mysql-escape-string.php)在本地工作,但它不尊重charset而且已被弃用.如果你考虑它,它是有道理的,只有MySQL可以使用其精确的字符集实现来转义字符串数据.替代准备语句的一个明显案例. (4认同)
  • 谢谢,我不知道`mysql_real_escape_string` 在调用时实际上与服务器通信;我只是假设在打开连接时存储了字符编码,并且 `mysql_real_escape_string` 在本地工作,使用存储的信息。 (2认同)