PDO的查询与执行
他们都做同样的事情,只是不同?
除了使用之间的prepare
之间有什么区别
$sth = $db->query("SELECT * FROM table"); $result = $sth->fetchAll();
和
$sth = $db->prepare("SELECT * FROM table"); $sth->execute(); $result = $sth->fetchAll();
?
query
运行标准的SQL语句,并要求您正确地转义所有数据以避免SQL注入和其他问题。
execute
运行一个准备好的语句,允许您绑定参数以避免需要转义或引用参数。 execute
也将执行更好,如果你重复查询多次。 准备报表的示例:
$sth = $dbh->prepare('SELECT name, colour, calories FROM fruit WHERE calories < :calories AND colour = :colour'); $sth->bindParam(':calories', $calories); $sth->bindParam(':colour', $colour); $sth->execute(); // $calories or $color do not need to be escaped or quoted since the // data is separated from the query
最好的做法是坚持准备好的陈述和execute
以提高安全性 。
另请参见: PDO准备的语句是否足以防止SQL注入?
不,他们不一样。 除了它提供的客户端转义之外, 一个准备好的语句在服务器端编译一次,然后可以在每次执行时传递不同的参数 。 这意味着你可以这样做:
$sth = $db->prepare("SELECT * FROM table WHERE foo = ?"); $sth->execute(array(1)); $results = $sth->fetchAll(PDO::FETCH_ASSOC); $sth->execute(array(2)); $results = $sth->fetchAll(PDO::FETCH_ASSOC);
他们通常会给你一个性能的提高,虽然小规模并不明显。 阅读更多的准备报表(MySQL版本) 。
Gilean的回答非常好,但是我只想补充一点,有时最好的做法很less有例外,你可能想用两种方法来testing你的环境,看看哪种方法最好。
在一个案例中,我发现query
对我的工作更快,因为我是从一个运行PHP7的Ubuntu Linux框中将受信任的数据批量传递给Microsoft SQL Server的微软ODBC驱动程序 。
我遇到了这个问题,因为我有一个ETL的脚本,我正在试图加快速度。 我觉得query
可能比prepare
和execute
更快,因为它只调用一个函数而不是两个函数。 参数绑定操作提供了极好的保护,但是如果不必要的话,这可能是昂贵的,可能会避免。
鉴于几个罕见的条件 :
-
如果您不能重复使用预备的语句,因为它不受Microsoft ODBC驱动程序的支持 。
-
如果你不担心消毒input和简单的逃避是可以接受的。 这可能是这种情况,因为Microsoft ODBC驱动程序不支持绑定某些数据types 。
-
Microsoft ODBC驱动程序不支持
PDO::lastInsertId
。
以下是我用来testing我的环境的一种方法,希望您可以在其中复制它或更好:
首先,我已经在Microsoft SQL Server中创build了一个基本的表
CREATE TABLE performancetest ( sid INT IDENTITY PRIMARY KEY, id INT, val VARCHAR(100) );
现在是性能指标的基本定时testing。
$logs = []; $test = function (String $type, Int $count = 3000) use ($pdo, &$logs) { $start = microtime(true); $i = 0; while ($i < $count) { $sql = "INSERT INTO performancetest (id, val) OUTPUT INSERTED.sid VALUES ($i,'value $i')"; if ($type === 'query') { $smt = $pdo->query($sql); } else { $smt = $pdo->prepare($sql); $smt ->execute(); } $sid = $smt->fetch(PDO::FETCH_ASSOC)['sid']; $i++; } $total = (microtime(true) - $start); $logs[$type] []= $total; echo "$total $type\n"; }; $trials = 15; $i = 0; while ($i < $trials) { if (random_int(0,1) === 0) { $test('query'); } else { $test('prepare'); } $i++; } foreach ($logs as $type => $log) { $total = 0; foreach ($log as $record) { $total += $record; } $count = count($log); echo "($count) $type Average: ".$total/$count.PHP_EOL; }
我在特定的环境中玩过多种不同的testing和计数,并且query
结果比prepare
/ execute
结果要持续20-30%
5.8128969669342准备
5.8688418865204准备
4.2948560714722查询
4.9533629417419查询
5.9051351547241准备
4.332102060318查询
5.9672858715057准备
5.0667371749878查询
3.8260300159454查询
4.0791549682617查询
4.3775160312653查询
3.6910600662231查询
5.2708210945129准备
6.2671611309052准备
7.3791449069977准备
(7)准备平均:6.0673267160143
(8)查询平均:4.3276024162769
我很好奇,看看这个testing如何在其他环境中比较,如MySQL。