首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL PDO准备得比查询更快?这就是这个简单的测试所显示的

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

Stack Overflow用户
提问于 2013-01-04 23:38:38
回答 2查看 4.9K关注 0票数 8

下面是我运行的一个简单测试,它可以快速了解使用MySQL准备语句和使用直接查询时的性能损失。person表中有2801行。MySQL版本5.5.28和PHP5.3.15。普通安装,无论默认参数是什么。测试运行在8GB的iMac上。

代码语言:javascript
复制
$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);

这是输出:

代码语言:javascript
复制
query: 21.010436058044

prepare/execute: 20.74036192894

这表明根本没有处罚。可能性:

  • 准备好的语句的缓存非常有效。(注意,我将准备函数保存在循环中。)
  • 这是个假测试,因为它太简单了。
  • 没有理论上的理由说明为什么准备/执行应该慢一些,而且,由于厌倦了不断的批评,MySQL/PDO/PHP开发人员特别努力地让他们更快地工作,试图让我们所有人闭嘴。
  • 另一个?

这里曾多次说过,使用准备好的语句比使用查询更安全,对于PDO中的命名参数(Mysqli没有它们),处理参数非常方便。但是,我们经常注意到,如果每次执行语句时都必须准备语句,则会导致性能损失。

那么,有人能提供一些与我的简单测试相矛盾的测试吗?或者,我们现在应该承认,没有理由不使用预先准备好的声明吗?

EN

回答 2

Stack Overflow用户

发布于 2013-01-05 00:16:44

有一件小事要提。默认情况下,PDO只是模仿准备好的语句。

在模拟模式下,它运行相同的旧查询,而不实际准备一条语句:)

所以首先

代码语言:javascript
复制
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);

打开真正准备好的声明。

正如人们经常指出的那样,这是一种绩效惩罚。

还有一件小事要提。

可悲的是,世界上几乎没有真正的知识。尤其是在问答网站的世界。人们倾向于重复他们读过的信息,发现这些信息是合理的。不做任何测试来证明,甚至不把手放在上面。因此,“经常注意到”根本不应该被认为是一个可靠的来源。

回到问题:虽然应该有一些处罚,但它应该是微不足道的大部分时间。如果是的话-你必须调整你的系统。

无论如何,在模拟模式下,您可以获得“快速”和“安全”。

更新

在对我的数据进行测试之后,我不得不说,如果在大型数据集上有3倍的差异,那么数据库就有问题了。

对于闪电查询

代码语言:javascript
复制
select title from Board where id = 1

结果是

代码语言:javascript
复制
emulation   on      off
query      0.07    0.130
prepare    0.075   0.145

而对于相当繁重的查询

代码语言:javascript
复制
select title from Board where id > 1

结果是

代码语言:javascript
复制
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的我自己的类中,我使用自己的占位符实现,完全不使用准备好的语句。不是出于性能原因,而是为了更好的可靠性。

票数 11
EN

Stack Overflow用户

发布于 2013-01-04 23:59:56

我对你的方法有一些问题:

  1. 除非服务器上绝对没有任何其他东西与脚本同时运行,这是不太可能的,否则您的基本计时器会受到CPU调度的影响。要解决这个问题,请编写两个独立的脚本,并使用*nix的time命令(即:time php myscript.php )运行它们
  2. 由于mySQL缓存查询,颠倒脚本的顺序可能会产生相同的结果。
  3. 每个测试都不是诊断的结果。尝试运行每个脚本几百次或几千次,然后平均结果以获得更全面的结果。

但是,在非静态查询的情况下,仍然没有理由不使用准备好的语句,除非您喜欢始终严格地验证所有输入,并且仍然有可能进行SQL注入。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14166798

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档