【问题标题】:Mysql PDO Prepared statement efficiencyMysql PDO Prepared statement 效率
【发布时间】:2011-07-24 22:12:32
【问题描述】:

我正在接管一个 PHP 应用程序,该应用程序在每次运行 SQL 语句时都使用 MySQL PDO 准备语句。 我知道当您要对同一条语句进行多次迭代时,准备 SQL 会更有效率。

$sth = $dbh->prepare('SELECT name, colour, calories
FROM fruit
WHERE calories < ? AND colour = ?');
$sth->execute(array(150, 'red'));
$red = $sth->fetchAll();
$sth->execute(array(175, 'yellow'));
$yellow = $sth->fetchAll();

但是,我正在接管的应用程序在 PDO 之上构建了一个层,该层调用一个常见的“执行”函数,并且它似乎准备了每个 SQL 查询。例如:

$query = self::$DB->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$query->execute($bindvars);

如果应用程序执行数百或数千个“INSERT INTO ...... ON DUPLICATE KEY UPDATE”SQL 语句,如果 $DB->prepare() 步骤每次都运行,它是否会产生大量开销?

非常感谢,杰森。

【问题讨论】:

  • 一个很好的问题我要标记的是:如果一个人再次准备相同的语句,那是否被捕获 & 是否使用了已经准备好的语句?

标签: php mysql pdo prepared-statement


【解决方案1】:

除了查询重用之外,在 PDO 中使用预准备语句的主要原因是执行占位符绑定。

$query = self::$DB->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$query->execute($bindvars);

在此代码中,$sql 变量中的问号(或:named)占位符被替换$bindvars 数组中的值。这种替换确保变量被正确引用和转义,使得执行SQL injection变得更加困难。

在准备/执行过程中可能会有少量开销,但考虑到 SQL 注入的风险,这个小开销没什么。唯一的其他选择是将 SQL 字符串连接在一起,这可能会带来巨大的安全风险,除非每次都都做到这一点。

至少在这种特定情况下,前一个开发人员知道他或她在做什么,您不应该撤消他或她在这里所做的工作。恰恰相反,你应该在你以后的所有代码中继续使用准备好的语句。

(另一方面,我不能保证 MySQL 的游标性能......)

【讨论】:

  • OP 并没有真正询问是否使用 PDO - 重量应该在“调用准备多次伤害吗?”部分。
  • @Jon,我的论点是,许多准备好的语句可能对性能造成的影响都被准备好的语句本身的好处所抵消。
  • @Charles:没有人怀疑准备好的语句的好处。这只是准备相同语句的次数。 :)
  • @Jon,我没有从问题中得到“多次准备 same 语句”的内容,除非我误解了关于有数百个的部分成千上万的INSERT INTO ... ON DUPLICATE KEY UPDATEs,在这种情况下,我不清楚他是否在谈论许多不同的查询,或者他是否在谈论未能重用准备好的语句。如果是后者,那么这绝对是应该解决的问题。我只是不想看到有人降级,仅此而已。 :)
  • @Jon - “他是否在谈论未能重用准备好的语句。”,是的,这就是这里发生的事情。杰森
【解决方案2】:

来自文档:

调用 PDO::prepare() 和 PDOStatement::execute() 用于语句 将多次发布 具有不同的参数值 优化您的性能 应用程序通过允许驱动程序 协商客户端和/或服务器端 缓存查询计划和元数据 信息...

我在这里并没有真正做出任何启示,但“优化性能”的反面确实是“开销”。至于它是否重要,你为什么不运行一个循环并测量?然后,您可以自己决定用硬数据来支持您的决定。

【讨论】:

    【解决方案3】:

    如果内存正常,MySQL 会看到您准备好的语句,并认为您可能正在运行一个可能多次调用同一语句的应用程序。因此,它缓存语句字符串,因此再次准备它并没有太多开销,尽管它不仅仅是将语句的引用保存在内存中。它仍然肯定比每次从字符串解析一个全新的查询要好。

    不过,这只是我对自己听到的模糊记忆。这是重要的一点:如果这成百上千的插入在同一个请求中运行,请考虑重构数据库类以在此类情况下准备一次并执行多次。了解它会产生多大影响的唯一方法是自己进行基准测试:/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-26
      • 2011-01-07
      • 2012-08-18
      • 1970-01-01
      • 2014-10-23
      • 2014-12-17
      • 2014-02-24
      相关资源
      最近更新 更多