2011-06-10 30 views
3

我正在更新/修改某些数据库代码,我想知道,我应该用什么真的期望使用预准备语句。MySQL准备好的语句与普通查询。收益和损失

拿这个例子代码:
(裸着我,我知道这是丑陋的 - 我自己写的)

$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服务器有什么影响吗?

假设一切都正确索引。

+0

可能的重复[在PHP PERFORMANCE-WISE中应该使用MySQL语句吗?](http:// stackoverflow.com/questions/2214408/should-i-use-prepared-statements-for-mysql-in-php-performance-wise) – e4c5 2016-04-24 02:14:34

回答

7

通常情况下,如果你只是代替普通的查询使用准备好的语句,因为查询准备分两步执行它或多或少地更慢而不是一个。准备好的陈述只有在准备陈述并多次执行时才会变得更快。

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

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

我的建议是总是使用准备好的语句。在他们增加边际性能开销的情况下,它们对于安全性(无SQL注入)和可读性好处仍然值得。当然,任何时候你发现自己求助于mysql_real_escape_string,你应该使用准备好的语句。 (对于简单的一次性查询,在不需要跳过变量输入的情况下,它们不是必须的。)

+0

谢谢,我不知道'mysql_real_escape_string'实际上与服务器通信时调用;我只是假定当你打开一个连接时存储字符编码,'mysql_real_escape_string'在本地工作,使用存储的信息。 – OpiF 2011-06-10 04:02:46

+3

是的,它应该在PHP文档中更加突出,它可以做到这一点。字节流被发送到MySQL,使用其字符集设置转义并返回转义字符串...如果打开MySQL服务器的查询日志,您将看到所有这些“查询”。有一个旧的[mysql_escape_string](http://php.net/manual/en/function.mysql-escape-string.php)可以在本地使用,但它不尊重字符集,因此不推荐使用。如果你仔细想想,这是有道理的,只有MySQL可以使用其精确的字符集实现来转义字符串数据。而是准备好的陈述的一个明显例子。 – joelhardi 2011-06-10 04:30:41

+0

@joelhardi您对'mysql_real_escape_string'的评论非常有趣。这是否也适用于mysqli对象?有没有任何基准显示开销是多少?我一直认为使用预先准备好的语句,只要你一次计划执行一次查询是没有意义的,所以有兴趣知道你需要运行多少个real_escape_strings,而执行一次准备好的语句才能使后者更高效。我猜这是微型优化,但对所有相同的感兴趣。 – texelate 2016-11-23 07:48:58

1
  1. 准备好的语句更安全。
  2. 准备好的语句具有更好的性能。
  3. 编写的语句编写起来更方便。

你会读所有这些!

http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html

试试这个太

Prepared Statement vs. Stored Procedure

+3

2.取决于上下文。这是你的意见。 – texelate 2016-11-23 07:45:20

+1

准备好的语句非常好(特别是如果你有像用户输入一样的安全问题),texelate是完全正确的,并且忘记提及它们读取/调试的方便性。就我个人而言,我很少操纵用户输入,尽可能避免准备查询,通常是因为在需要修复失败的请求时,如果没有其实际的SQL内容,它不会带来更大的麻烦。他们仍然很棒,但有*也有*理由不使用它们:) – Balmipour 2017-07-04 16:44:20