为什么我没有看到我期望在准备和未准备的查询之间看到的巨大性能差异?

时间:2016-12-20 19:27:25

标签: php pdo prepared-statement

我认为,当逐个循环遍历一千条记录时,我会看到使用 PDO语句 PDO查询之间的显着性能差异。

我为每个人做了一千次循环,得到了平均结果,他们都反映了几乎相同的时间(≈0.105秒)。为什么?我本以为准备好的陈述是最快的。

以下是我用于测试目的的代码:

$iter = 1000;
$idAry = range(1,1000);
$sumResultAry = array();

// [TEST1]
$func1 = function($id,array &$sumResultAry){
    list($dbCon,$DB,$TP) = AClass::retrieve_database_properties_();
    $sql = "
        SELECT 
            t1.id,
            t1.look_key
        FROM {$DB}.{$TP}test t1 
        WHERE 
            t1.id={$id} 
    ";

    if(false!==($result=$dbCon->query($sql))){
        if(false!==($row=$result->fetch(PDO::FETCH_ASSOC))){
            $sumResultAry[] = $row['id'];
        }
    }
};

$wh = fopen('test','w');
if($wh){
    for($i=0;$i<$iter;++$i){
        $startTime = microtime(true);
        foreach($idAry as $id){
            $func1($id,$sumResultAry);
        }
        $endTime = number_format((microtime(true)-$startTime),4);
        fwrite($wh,$endTime . "\n");
    }

    fclose($wh);
}

$result = 0;

$rh = fopen('test','r');
if($rh){
    while(!feof($rh)){
        $line = trim(fgets($rh));
        if($line!==''){
            $result += floatval($line);
        }
    }

    fclose($rh);
}

echo '<pre>';
echo 'test query' . "\n\n";
echo 'time: ' . ($result/$iter) . ' seconds' . "\n\n";
echo '</pre>';
// [/TEST1]

// [TEST2]
$func2 = function($id,array &$sumResultAry){
    $key = 'test';
    $sqlStmt = null;
    if(null===($sqlStmt=AClass::return_sqlStatement_($key))){// retrieving statement if previously stored
        list($dbCon,$DB,$TP) = AClass::retrieve_database_properties_();
        $sql = "
            SELECT 
                t1.id,
                t1.look_key
            FROM {$DB}.{$TP}test t1 
            WHERE 
                t1.id=:id
        ";
        if(AClass::prepare_sqlStatement_($key,$sql)){// preparing and storing statement
            $sqlStmt = AClass::return_sqlStatement_($key);
        }
    }
    if(null!==$sqlStmt){
        if(false!==($sqlStmt->execute(array(':id'=>$id)))){
            if(false!==($row=$sqlStmt->fetch(PDO::FETCH_ASSOC))){
                $sumResultAry[] = $row['id'];
            }
        }
    }
};

$wh = fopen('test','w');
if($wh){
    for($i=0;$i<$iter;++$i){
        $startTime = microtime(true);
        foreach($idAry as $id){
            $func2($id,$sumResultAry);
        }
        $endTime = number_format((microtime(true)-$startTime),4);
        fwrite($wh,$endTime . "\n");
    }

    fclose($wh);
}

$result = 0;

$rh = fopen('test','r');
if($rh){
    while(!feof($rh)){
        $line = trim(fgets($rh));
        if($line!==''){
            $result += floatval($line);
        }
    }

    fclose($rh);
}

echo '<pre>';
echo 'test statement' . "\n\n";
echo 'time: ' . ($result/$iter) . ' seconds' . "\n\n";
echo '</pre>';
// [/TEST2]

感谢你们中的一些人,我现在明白我需要使用更复杂的查询来测试两者之间的显着性能差异。

2 个答案:

答案 0 :(得分:4)

无论如何,我不确定你会看到'大规模'的性能差异,除非你运行了很多迭代。

创建预准备语句并使用一组参数提交它将比单个查询运行的静态查询(对于单个查询和一组参数)花费更多的时间。稍微说,我们说的是毫秒级或几分之一毫秒的球场。

从准备好的语句中获得的内容(如果您的数据库支持它们)是:

  • SQL注入保护
  • 使用不同的参数多次运行相同的查询时加速(如在循环中),因为数据库只创建一个执行计划。通常,您需要运行相当多的执行才能看到任何明显的内容。

如果它是一个快速,索引良好的查询,它本身只需要几毫秒的时间来运行,并且有一个简单的构建执行计划,那么你可能需要运行数千个请求,以便通过一个准备好的语句获得任何显着的改进。静态查询。

所以,只需使用预备语句,因为它通常更好。

答案 1 :(得分:0)

  

为什么我没有看到我希望在准备好的和未准备好的查询之间看到的巨大性能差异?

因为没有。

我不知道你从哪里得到这个想法,但是没有一个准备好的声明给你甚至显着的性能差异,更不用说“大规模”了。 即使使用得当