我正在更新/重新编写一些数据库代码,我想知道我应该从使用准备好的语句中得到什么。

以这个示例代码为例:

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

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

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

最佳答案

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

但是,在这种情况下,您使用的是 mysql_real_escape_string ,它会往返数据库。更糟糕的是,您是在循环中执行此操作,因此每个查询执行多次。因此,在这种情况下,用单个准备好的语句替换所有这些往返是双赢的。

关于您的最后一个问题,您没有理由不能像通过普通查询解析器那样在准备好的语句中使用相同的查询(即没有理由使用 IN 执行一个版本,另一个使用一堆 OR)。 prepared statement 可以有 IN (?, ?, ?) ,然后您只需绑定(bind)该数量的参数。

我的建议是始终使用准备好的语句。在它们增加边际性能开销的情况下,对于安全性(无 SQL 注入(inject))和可读性优势,它们仍然值得。当然,无论何时您发现自己求助于 mysql_real_escape_string ,您都应该改用准备好的语句。 (对于不需要转义变量输入的简单一次性查询,它们不是绝对必要的。)

10-07 19:52
查看更多