Php MySQL PDO准备得比查询快吗?那';这就是这个简单的测试所显示的

Php MySQL PDO准备得比查询快吗?那';这就是这个简单的测试所显示的,php,mysql,pdo,prepared-statement,Php,Mysql,Pdo,Prepared Statement,下面是一个简单的测试,我运行这个测试是为了快速了解使用MySQL-PDO准备的语句与使用直接查询相比会带来的性能损失。person表中有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 < 20

下面是一个简单的测试,我运行这个测试是为了快速了解使用MySQL-PDO准备的语句与使用直接查询相比会带来的性能损失。person表中有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);
这表明根本没有处罚。可能性:

  • 对准备好的语句进行缓存确实有效。(注意,我将prepare函数保留在循环中。)

  • 这是一个虚假的测试,因为它太简单了

  • 从理论上讲,没有理由认为prepare/execute应该更慢,而且,MySQL/PDO/PHP开发人员已经厌倦了不断的批评,为了让我们大家闭嘴,他们付出了额外的努力来加快速度

  • 其他的

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


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

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

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

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

    有一点需要提及。默认情况下,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
    
    emulation   on      off
    query      0.96    0.96
    prepare    0.96    1.00
    
    而对于相当繁重的查询

    select title from Board where id > 1
    
    结果是

    emulation   on      off
    query      0.07    0.130
    prepare    0.075   0.145
    
    emulation   on      off
    query      0.96    0.96
    prepare    0.96    1.00
    
    因此,正如我们所看到的,在大型数据集上,差异变得不明显

    对于lightning查询有一些不同,但是,因为它只需要00003秒(对于单个查询)-我认为这是“冷漠”一词的完美例子

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

    现在转到编码问题。

    是的,奇怪的GBK问题确实会影响5.3.3之前版本的PDO。这些版本无法设置正确的编码,并且不可避免地易受攻击(在模拟模式下)。但是由于5.3.3 PDO支持在DSN中设置编码,现在一切都正常了。
    对于mysqli,必须使用
    mysqli\u set\u charset()
    来达到同样的目的(不可穿透)


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

    1)很棒2)是3)“谁在乎?”-使用准备好的语句。为了达到这个目的,可以尝试使用更多查询再次运行它,并尝试交换顺序(先准备好)。我原以为准备好的语句会比直接查询更快,基于准备好的语句中的SQL每次都是相同的。它允许将查询解析缓存在数据库服务器中,如果您不断更改未准备的
    WHERE
    子句,这是不可能的。您所说的时间几乎不值得注意。哈弗:我不明白您的逻辑。由于函数的参数没有改变,缓存(客户端、服务器,无论在何处)的机会是相同的。然后问题4:在循环中进行准备是愚蠢的。因为这是准备/执行成本的计时测试,不将准备放在循环中会使测试无效。(这是一个计时测试,而不是编写程序的方法!)非常好的观点。当我关掉它时,时间下降到原来的三分之一左右。但是准备好的和未准备好的案例都是如此。然而,顺序是互换的:它不再是一根更快的头发,而是一根更慢的头发。(街上的说法是准备的速度要慢得多,所以我把我得到的时间称为——7.5秒,而200次迭代的时间是7.3秒——平局。)关于仿真的问题:一个问题是