【问题标题】:Speed/best practice flushing mysqli_multi_query()刷新 mysqli_multi_query() 的速度/最佳实践
【发布时间】:2014-03-20 11:44:40
【问题描述】:

当 Sebastien 说他在每次使用 mysqli_multi_query() @@Can mysqli_multi_query do UPDATE statements? 之间断开连接并重新连接时,我感到畏缩,因为这似乎不是最佳实践。

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

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

我也很高兴听到与速度无关的任何/所有问题。 Craig 使用连接函数对速度有影响吗?

克雷格的while语句是否有速度差异:

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

- 与 -

我建议的 while 语句:

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

- 与 -

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

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

- 与 -

像塞巴斯蒂安和克雷格一样在每个mysqli_multi_query() 之间打开和关闭:

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

- 与 -

还有其他选择可以测试吗?

【问题讨论】:

    标签: php mysqli benchmarking mysqli-multi-query


    【解决方案1】:

    这不是next_result() 的责任,而是在质疑自己。代码运行时间取决于实际查询的执行时间。

    虽然mysqli_multi_query() 很快返回控制权,这并不意味着到那时所有查询都已执行。 恰恰相反,当mysqli_multi_query() 完成时,只有第一个查询得到执行。 而所有其他查询都在 mysql 端排队等待 异步 执行。

    由此您可能会得出结论,next_result() 调用本身不会添加任何超时 - 它只是在等待下一个查询完成。如果查询本身需要时间,那么next_result() 也必须等待。

    知道您已经知道选择哪种方式:如果您不关心结果,您可以关闭连接。但实际上,它只是扫除地毯下的污垢,将所有缓慢的查询留在原地。因此,最好保留next_result() 循环(尤其是因为您必须检查错误/受影响的行/等等),但要加快查询速度。

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

    1. 对于选择查询,它通常是索引/解释分析,已在其他答案中解释。
    2. 对于 DML 查询,尤其是批量运行,还有其他方法:

    说到 Craig 的案例,它非常类似于已知的 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。

    【讨论】:

    • 我以前从未在 SO 上看到过赏金。根据 SO bounty 帮助页面 [stackoverflow.com/help/bounty],您不必成为提问者就可以在问题上悬赏。如果您认识任何拥有数万代表点的人,我提前感谢他们设置赏金。显然,50 分的最低赏金真的会打破我的存钱罐并剥夺我几乎所有可能的特权。
    • 嘿。这是您似乎感兴趣的答案的唯一部分。
    • +1 以获得很好的答案,指出编程选择的真正问题和可能的“副作用”。
    • "多值插入语法" - 感谢这样做,我的插入速度提高了 40 倍。
    【解决方案2】:

    回答你的问题:

    跳之前先看看

    我希望您的 mysqli_more_results() 调用(跳转前的查看)不会加快速度:如果您有 n 个结果,您将对数据库进行 (2*n)-1 调用,而 Craig 会n+1。

    多个连接

    multi_queryexecutes async,所以你只会增加连接开销。

    打开和关闭数据库

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

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

    相反,试着记住

    没有勺子

    在您的示例中,不需要多个查询。 INSERT ... VALUES 表单采用多个元组作为 VALUES。因此,不要准备一个准备好的语句并将其重复执行包装在事务like Your Common Sense suggest 中。您可以准备一条语句并让它执行并自动提交。根据mysqli manual,这可以为您节省大量往返时间。

    所以做一个如下形式的 SQL 语句:

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

    并绑定并执行它。 mysqldump --opt 做到了,那我们为什么不呢? mysql 参考手册为section on statement optimization。在其 DML 部分中查找插入和更新查询。但是了解--opt 为何会这样做是一个好的开始。

    准备陈述的低估价值

    对我来说,准备好的语句的真正价值不是你可以多次执行它们,而是自动输入转义。对于一个微不足道的额外客户端-服务器往返,您可以避免 SQL 注入。 SQL 注入是一个重要的注意点,尤其是当您使用multi_query 时。 multi_query 告诉 mysql 期望多个查询并执行它们。因此,如果无法正确逃脱,那么您将获得一些乐趣:

    所以我的最佳做法是:

    1. 真的需要多个查询吗?
    2. 如果我这样做了,逃离他们,或者准备他们!

    【讨论】:

    • 虽然我的回答确实提到了重复插入的特殊情况,但 question 甚至没有任何痕迹。而且这个问题的问题与您想在回答中讨论的两个主题相距太远。
    • @YourCommonSense 我已调整答案以更清楚地解决问题。
    • 这是一个有趣的类型 - 以答案的形式对其他答案的评论。尽管您在其中提出了一些观点,但您未能明确回答特定问题。
    • @YourCommonSense 有趣...也许维基答案会更好。我,不太明白为什么我会故意失败。我不是母语人士。您的意思是否不同于说:“在 TDD 中,我故意使测试失败,然后编写代码使其通过”?
    • 我也不是。我已经改了这个词。问题本质上是:为什么 next_result 这么慢。答案是:这不是 next_result 的责任。
    猜你喜欢
    • 2010-09-26
    • 2019-09-09
    • 2018-11-02
    • 2015-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-16
    相关资源
    最近更新 更多