多次准备语句时的性能问题

时间:2013-09-23 15:49:29

标签: mysql sql performance postgresql prepared-statement

我有一个PHP应用程序,它使用PDO和PostgreSQL和MySQL中的预处理语句,我想知道在执行它之前每次准备完全相同的语句是否会有性能损失。

在伪代码中,一个例子是:

for ($x=0; $x<100; $x++) {
    $obj = PDO::prepare("SELECT x,y,z FROM table1 WHERE x=:param1 AND y=:param2");
    $obj->execute(array('param1'=>$param1, 'param2'=>$param2));
}

与准备一次并多次执行相反:

$obj = PDO::prepare("SELECT x,y,z FROM table1 WHERE x=:param1 AND y=:param2");
for ($x=0; $x<100; $x++) {
    $obj->execute(array('param1'=>$param1, 'param2'=>$param2));
}

我多次搜索过这个问题,但似乎无法在PHP,PostgreSQL和MySQL中找到它的引用。

3 个答案:

答案 0 :(得分:1)

是的,它在某种程度上违背了使用准备好的陈述的目的。准备允许DB预先解析查询并准备好执行。当您执行该语句时,数据库只会滑入您提供的值并执行最后几个步骤。

当你在这样的循环内准备时,所有的准备工作都会被抛出并每次都重新完成。你应该拥有的是:

$obj = PDO::prepare("SELECT x,y,z FROM table1 WHERE x=:param1 AND y=:param2");
for ($x=0; $x<100; $x++) {
    $obj->execute(array('param1'=>$param1, 'param2'=>$param2));
}

准备一次,执行多次。

答案 1 :(得分:0)

是的,性能受到了打击。准备步骤必须解析SQL字符串并对其进行分析以确定它需要访问哪些表以及它将如何执行(要使用哪些索引等)。因此,如果您在循环开始之前准备一次(),然后在循环内执行(),这可以节省成本。

这是一个更通用的编程原则的示例:如果代码的结果对于循环的每次迭代都相同,则不应将代码放在循环中。

PS:你不应该使用PDO::prepare(),你应该创建一个PDO对象并调用$pdo->prepare()

PPS:您还应该检查prepare()和execute()的返回值。他们会在错误时返回 false 。或者配置PDO以在出错时抛出异常。

答案 2 :(得分:0)

为什么不这样做?它当然会执行求解器。但由于在准备过程中没有与数据库连接或进行繁重的计算(因为查询很短),速度变化将是微不足道的,但这是一种糟糕的风格。

$obj = PDO::prepare("SELECT x,y,z FROM table1 WHERE x=:param1 AND y=:param2");
for ($x=0; $x<100; $x++) {
    $obj->execute(array('param1'=>$param1, 'param2'=>$param2));
}