下面是我运行的一个简单测试,它可以快速了解使用MySQL准备语句和使用直接查询时的性能损失。person表中有2801行。MySQL版本5.5.28和PHP5.3.15。普通安装,无论默认参数是什么。测试运行在8GB的iMac上。
$pdo = new PDO('mysql:host=localhost;dbname=cwadb_local', 'root', "");
$start = microtime(true);
for ($i = 0; $i < 200; $i++) {
$pdo->query("select * from person where name_last = 'smith' or true");
}
echo "<p>query: " . (microtime(true) - $start);
$start = microtime(true);
for ($i = 0; $i < 200; $i++) {
$stmt = $pdo->prepare("select * from person where name_last = :last or true");
$stmt->execute(array('last' => 'smith'));
}
echo "<p>prepare/execute: " . (microtime(true) - $start);这是输出:
query: 21.010436058044
prepare/execute: 20.74036192894这表明根本没有处罚。可能性:
这里曾多次说过,使用准备好的语句比使用查询更安全,对于PDO中的命名参数(Mysqli没有它们),处理参数非常方便。但是,我们经常注意到,如果每次执行语句时都必须准备语句,则会导致性能损失。
那么,有人能提供一些与我的简单测试相矛盾的测试吗?或者,我们现在应该承认,没有理由不使用预先准备好的声明吗?
发布于 2013-01-05 00:16:44
有一件小事要提。默认情况下,PDO只是模仿准备好的语句。
在模拟模式下,它运行相同的旧查询,而不实际准备一条语句:)
所以首先
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);打开真正准备好的声明。
正如人们经常指出的那样,这是一种绩效惩罚。
还有一件小事要提。
可悲的是,世界上几乎没有真正的知识。尤其是在问答网站的世界。人们倾向于重复他们读过的信息,发现这些信息是合理的。不做任何测试来证明,甚至不把手放在上面。因此,“经常注意到”根本不应该被认为是一个可靠的来源。
回到问题:虽然应该有一些处罚,但它应该是微不足道的大部分时间。如果是的话-你必须调整你的系统。
无论如何,在模拟模式下,您可以获得“快速”和“安全”。
更新
在对我的数据进行测试之后,我不得不说,如果在大型数据集上有3倍的差异,那么数据库就有问题了。
对于闪电查询
select title from Board where id = 1结果是
emulation on off
query 0.07 0.130
prepare 0.075 0.145而对于相当繁重的查询
select title from Board where id > 1结果是
emulation on off
query 0.96 0.96
prepare 0.96 1.00因此,正如我们所看到的,在大型数据集上,差异变得不明显。
对于闪电查询,有一些不同,但是,由于它只需要0,0003个派别的第二(一个查询)-我想说,这是一个完美的例子,“冷漠”。
对于query()/prepare() --我只有一个想法-- PDO对所有查询,甚至那些没有绑定的查询,都使用准备/执行。
现在谈到编码问题.
是的,奇怪的GBK问题确实会影响以前版本的PDO。这些版本无法设置正确的编码,并且不可避免地易受攻击(在模拟模式下)。但是由于5.3.3PDO支持在DSN中设置编码,所以现在一切都好了。
对于mysqli来说,我们必须使用mysqli_set_charset()来达到这个目的,其结果是相同的(不可穿透的)。
在基于mysqli的我自己的类中,我使用自己的占位符实现,完全不使用准备好的语句。不是出于性能原因,而是为了更好的可靠性。
发布于 2013-01-04 23:59:56
我对你的方法有一些问题:
time命令(即:time php myscript.php )运行它们但是,在非静态查询的情况下,仍然没有理由不使用准备好的语句,除非您喜欢始终严格地验证所有输入,并且仍然有可能进行SQL注入。
https://stackoverflow.com/questions/14166798
复制相似问题