我正在接管一个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-&gt; prepare()步骤是否会在每次运行时产生大量开销时间?
非常感谢,杰森。
答案 0 :(得分:3)
来自文档:
调用PDO :: prepare()和 PDOStatement :: execute()用于语句 将多次发布 具有不同的参数值 优化你的表现 应用程序允许驱动程序 协商客户端和/或服务器端 缓存查询计划和元 信息...
我这里并没有真正做出任何启示,但“优化表现”的反面确实是“开销”。至于它是否重要,为什么不以任何方式运行循环并测量?然后,您可以自行决定使用硬数据来支持您的决定。
答案 1 :(得分:2)
除了查询重用之外,在PDO中使用预准备语句的主要原因是执行占位符绑定。
$query = self::$DB->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$query->execute($bindvars);
在此代码中,:named
变量中存在的问号(或$sql
)占位符使用$bindvars
数组中的值替换。此替换可确保变量被正确引用和转义,从而使执行SQL injection变得更加困难。
准备/执行可能会有少量开销,但考虑到SQL注入的风险,这个小开销是 nothing 。唯一的另一个选择是连接SQL字符串,这可能是一个巨大的安全风险,除非每次完成完全 。
以前的开发人员知道他或她在做什么,至少在这个特定情况下,你不应该撤消他或她在这里所做的工作。恰恰相反,您应该继续在将来的所有代码中使用预准备语句。
(另一方面,我无法保证MySQL的游标性能......)
答案 2 :(得分:1)
如果内存服务,MySQL会看到你准备好的语句,并期望你可能正在运行一个可能多次调用同一语句的应用程序。因此,它会缓存语句字符串,因此再次准备它并不需要太多开销,尽管它不仅仅是在内存中保留对语句的引用。它绝对比每次从字符串解析一个全新的查询更好。
这只是我对我所听到的内容的模糊记忆。这是重要的一点:如果在同一个请求中运行这些数百或数千个插入,请考虑重构数据库类以准备一次并在这些情况下执行多次。了解它将产生多大差异的唯一方法是自己进行基准测试:/