微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

php – MySQL PDO准备比查询更快?这就是这个简单的测试所显示的

这是一个简单的测试,我试图快速了解使用 MySQL PDO预处理语句与使用直接查询所支付的性能损失.人员表中有2801行. MysqL版本5.5.28和 PHP版本5.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

显示没有任何惩罚.可能性:

>准备好的语句的缓存确实有效. (注意我将prepare函数保留在循环中.)
>这是一个虚假的测试,因为它太简单了.
>没有理论上的原因,为什么准备/执行应该更慢,并且厌倦了不断的批评,MysqL / PDO / PHP开发人员更加努力地使它们更快,以试图让我们所有人闭嘴.
>其他?

这里有很多次说使用预处理语句比使用查询更安全,并且在PDO中使用命名参数(MysqLi没有它们),处理参数非常方便.但是,正如经常指出的那样,如果必须在每次执行时都准备好语句,那么就会有性能损失.

那么,有人可以提供一些与我的简单测试相矛盾的测试吗?或者,我们现在是否承认没有理由不使用准备好的陈述?

有一件事要提.认情况下,PDO只是模拟预准备语句.
而在仿真模式下,它运行相同的旧查询而不实际准备单个语句:)

所以,首先,

$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,FALSE);

准备好真实的准备陈述.

it’s just as often noted that there’s a performance penalty

还有一件事要提.
可悲的是,世界上几乎没有真正的知识.特别是在Q& A网站的世界.人们倾向于重复他们阅读过的信息,并认为合理.没有进行任何测试以证明甚至没有亲自动手.因此,“经常注意到”不应被视为可靠的来源.

回到这个问题:虽然应该有一些惩罚,但大部分时间都应该是微不足道的.如果是 – 您必须调整系统.

无论如何,在仿真模式下,你既“快速又安全”.

更新
好吧,在对我的数据运行测试之后,如果你在大型数据集上有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

因此,正如我们所看到的,在大型数据集上,差异变得不明显.

对于闪电查询存在一些差异,但是,因为它只需要第二万分之一(对于单个查询) – 我会说这是“无差异”一词的完美示例.

对于query()/ prepare()之间的相同结果 – 我只有一个想法 – PDO对所有查询使用prepare / execute,即使是那些没有绑定的查询.

现在来编码问题.

是的,奇怪的GBK问题确实影响了5.3.3之前版本的PDO.这些版本无法设置正确的编码,并且不可避免地容易受到攻击(在仿真模式下).但是由于5.3.3 PDO支持在DSN中设置编码,现在一切都很好.
对于MysqLi,必须使用MysqLi_set_charset()来达到这个目的,并使用相同的(不可穿透的)结果.

在我自己的基于MysqLi的类中,我使用自己的占位符实现并且根本不使用预处理语句.不是出于性能原因而是为了更好的可靠性

原文地址:https://www.jb51.cc/php/134688.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐