速度/最佳实践刷新mysqli_multi_query()

时间:2014-03-20 11:44:41

标签: php mysqli benchmarking mysqli-multi-query

当塞巴斯蒂安说他正在断开连接时,我畏缩了在mysqli_multi_query() @ Can mysqli_multi_query do UPDATE statements?的每次使用之间重新连接,因为它似乎不是最佳做法。

然而,Craig @ mysqli multi_query followed by query在他的案例中表示断开连接更快。在mysqli_multi_query()的每次使用之间重新连接,而不是使用mysqli_next_result()

我想问一下是否有人有进一步的第一手知识或基准证据来建议近似的"截止" (基于查询量或其他东西)当程序员应该选择"新连接"与#34;下一个结果"方法

我也很高兴听到任何/所有与速度无关的问题。 Craig使用连接功能是否与速度有关?

Craig在发表声明时是否存在速度差异:

while ($mysqli->next_result()) {;}

- 与 -

我建议的一段时间陈述:

while(mysqli_more_results($mysqli) && mysqli_next_result($mysqli));

- 与 -

在运行第一个multi_query之前为每个预期的multi_query创建一个新连接。我刚测试了这个,并且两个mysqli_multi_query()没有错误=不需要close()

$mysqli1=mysqli_connect("$host","$user","$pass","$db");
$mysqli2=mysqli_connect("$host","$user","$pass","$db");

- 与 -

Sebastien和Craig之间的每个mysqli_multi_query()之间的打开和关闭:

$mysqli = newSQL();
$mysqli->multi_query($multiUpdates);
$mysqli->close();

- 与 -

任何人都有另一种选择进行测试吗?

2 个答案:

答案 0 :(得分:9)

责备不是next_result(),而是查询自己。代码运行所需的时间取决于实际查询执行的时间。

虽然mysqli_multi_query()可以非常快地返回控件,但并不意味着所有查询都会在当时执行。相反,到mysqli_multi_query()完成时, 只执行了第一个查询。所有其他查询在mysql端排队等待异步执行。

通过这种方式,您可以得出结论:next_result()呼叫本身不会添加任何超时 - 它只是在等待下一个查询完成。如果查询本身需要时间,那么next_result()也必须等待。

知道您已经知道选择哪种方式:如果您不关心结果,可能会关闭连接。但事实上,它只是在地毯下扫除污垢,留下所有缓慢的查询。因此,最好保持next_result()循环(特别是因为你必须检查错误/受影响的行/等等),但加速查询本身。

因此,事实证明,要解决问题next_result(),您必须实际解决查询速度的常规问题。所以,这里有一些建议:

  1. 对于选择查询,它通常是索引/解释分析,已在其他答案中解释过。
  2. 对于DML查询,尤其是批量运行,还有其他方法:
  3. 说到克雷格的案例,它非常类似于已知的innodb写入速度问题。默认情况下,innodb引擎设置为非常谨慎的模式,在引擎确保前一个成功完成之前不会执行后续写入。因此,它使写入非常慢(类似于每秒10次查询)。对此的常见解决方法是立即进行所有写入。对于插入查询,有很多方法:

    • 您可以使用多个值插入语法
    • 您可以使用LOAD DATA INFILE查询
    • 您可以在事务中包装所有查询。

    虽然更新和删除只有交易仍然是可靠的方式。因此,作为一种通用的解决方案,可以提供这样的解决方法

     $multiSQL = "BEGIN;{$multiSQL}COMMIT;";
     $mysqli->multi_query($multiSQL);
     while ($mysqli->next_result()) {/* check results here */}
    

    如果它在您的情况下不起作用/不适用,那么我建议更改mysqli_multi_query()以便在循环中运行单个查询,调查并优化速度,然后返回到multi_query

答案 1 :(得分:2)

回答你的问题:

在你跳之前看看

我希望你的mysqli_more_results()调用(跳转之前的样子),不会加快速度:如果你有n个结果,你将对数据库进行(2 * n)-1次调用,而克雷格做n + 1。

多个连接

multi_query executes async,因此您只需添加连接开销。

打开和关闭db

Your Common Sense ;-)但是不要忘记你在做什么。在事务中包装查询将使它们成为atomic。这意味着,他们全部失败,或者他们全部成功。有时,必需使数据库永远不会与您的话语世界发生冲突。但是使用事务来加速,可能会产生不必要的副作用。考虑一下一个的查询违反约束的情况。这将使整个交易失败。这意味着如果它们首先不是逻辑事务并且大多数查询应该成功,那么您将必须找出哪个出错并且必须重新发布哪个。 成本计算你更多而不是提供加速。

Sebastien的查询实际上看起来应该是某个更大的交易的一部分,其中包含父母的删除或更新。

相反,请尝试并记住

没有勺子

在您的示例中,不需要多个查询。 INSERT ... VALUES形式为VALUES采用多个元组。因此,而不是准备一个预备语句并将其重复执行包装在事务like Your Common Sense suggest中。您可以准备一个语句并让它执行并自动提交。根据{{​​3}},这可以为您节省一些往返次数。

所以制作一个表格的SQL语句:

INSERT INTO r (a, b, c) VALUES (?, ?, ?), (?, ?, ?), ...

并绑定并执行它。 mysqldump mysqli manual做到了,为什么不呢? mysql参考手册为--opt。在其DML部分中查找插入和更新查询。但要理解为什么--opt做它的作用是一个好的开始。

低估了准备陈述的价值

对我来说,预备语句的实际值是,你可以多次执行它们,但是自动输入转义。对于一个可靠的单个额外客户端 - 服务器往返,您可以避免SQL注入。 SQL注入是一个严重的注意点,尤其是当您使用multi_query时。 multi_query告诉mysql 期待多个查询并执行它们。因此,如果没有正确逃脱,你就可以获得一些乐趣:

section on statement optimization

所以我的最佳做法是:

  1. 真的需要多次查询吗?
  2. 如果我这样做,逃脱他们,或准备他们!
相关问题