【发布时间】:2019-06-30 17:07:00
【问题描述】:
我正在尝试调试的一个 PHP 应用程序在一个更大的 MySQL 数据库上运行几个设计不佳的查询。
有几页真的很慢,原来是因为几个查询。我开始一一检查每个查询,虽然它们很慢,但它们本身并没有那么慢。
经过进一步调试,结果发现它们只是在应用程序将它们作为准备好的语句运行时才会变慢。
- 如果我通过 MySQL 客户端手动运行查询,大约需要 300 毫秒。如果我通过 MySQL 客户端运行 create aprepared statement 并设置参数并运行它,大约需要 300 毫秒。
- 如果我从 PHP (mysqli) 运行简单查询,大约需要 300 毫秒。
- 如果我像应用程序那样运行它——通过
mysqli——作为准备好的语句,它需要 100 秒。
我想可能是mysqli 所以我用 PDO 试了一下,结果是一样的。尝试了不同的 PHP 版本(5.6、7.2、7.3)并得到相同的结果。
所以我给了最后一次机会,写了一个小的 Go 脚本来测试,我得到了相同的结果并且事情得到了改进。
现在,如果我从 MySQL 客户端或 MySQL Workbench 或 PHPStorms 数据库客户端运行查询的准备语句版本,它会很快。如果我从代码中运行查询,它会非常快。
任何关于我应该注意什么,我应该在哪里继续调试的帮助将不胜感激。
【问题讨论】:
-
检查代码看它是否在循环中运行查询。在编码不佳的应用程序中看到这种情况并不少见。一个 300 毫秒的查询在一个循环中运行 300 次需要 90 秒。
-
遗憾的是,代码与此无关。我使用了一个纯脚本,它只包含两个版本的查询和执行时间的测量
-
尝试使用EXPLAIN 在这两个地方运行查询,看看是否存在可能导致问题的差异。
-
我们已经使用 EXPLAIN 运行了两个查询,执行计划是相同的,除了准备好的版本有一个带有
Uses index condition;Extra 的表。此外,查询只执行一次,循环中没有任何内容,唯一的区别是准备好的语句部分。参数的数量也不多(总共 9 个),它们也很简单(5 个整数,值为 0、1 和 2,以及 3 个短字符串)。在检查性能时,很明显所有负载都在 mysql 中,这会最大限度地利用 CPU。大多数情况下,查询处于sending data状态。