php - PDOStatement::fetchAll() 太慢

标签 php performance pdo fetchall

我遇到了一个 super 慢的 PDOStatement::fetchAll() ,这让我抓狂。 我的查询运行时间不到 0.1 秒。同样在 MySQL 终端中,我在不到 0.1 秒的时间内将输出显示在屏幕上。但是在 PDOStatement 上运行 fetchAll() 需要 2.5 秒。

// $_DB is my PDO class instance.
$tStart = microtime(true);
$q = $_DB->prepare('SELECT id FROM ... WHERE ... LIMIT 1000');
$q->execute($aArgs);
var_dump(round(microtime(true) - $tStart, 5));
$aIDsFiltered = $q->fetchAll(PDO::FETCH_COLUMN, 0);
var_dump(round(microtime(true) - $tStart, 5));exit;

这个输出:

float(0.0612)
float(2.58708)

好吧,认真的吗?我怎样才能在不到 0.1 秒的时间内在 MySQL 控制台中获得结果,而 PHP 却需要 2.5 秒来获取这 1000 个结果并将其放入一个简单的数组中?来吧,一个简单的 for 循环将 1000 个数字一个一个地放入一个数组中需要 0.001 秒......!!! 我在这里错过了什么?我可以使用什么作为替代品?我用谷歌搜索并搜索过,但找不到解决方案:(提前致谢!

编辑:fetchAll() 的持续时间不仅与返回结果的数量有关...而且与 $aArgs 的大小有关。不发送参数会使 fetchAll() 在 0.01 秒内返回,即使有 50K 个结果!为 execute() 调用提供 47K 个参数会使 fetchAll() 运行 120 秒。但这不是导致这种情况的大查询字符串的创建(顺便说一句,execute() 不是这样做的吗?),因为相同的 47K 参数,但 LIMIT 到 1K 结果只需要 2.5 秒...... 正如建议的那样,我已经验证 PDO 的 EXPLAIN 输出与使用 MySQL 控制台的输出相同。我也没有看到 MySQL 在努力工作,一直以来都是 Apache 进程(因此是 PHP)在占用 CPU。 另外:使用旧的 mysql_* 接口(interface),获取结果需要 0.03 秒。

背景信息

对于好奇的人:

  • 它是本地 MySQL 5.5 数据库,因此不是远程服务器。
  • PHP 版本:5.4.4。
  • 这里的用例是系统中有许多过滤器(一个过滤器 = 一个数据库查询),以用户最喜欢的顺序运行,其中每个过滤器都从前一个过滤器中获取匹配条目的 ID运行,它应该返回剩余匹配条目的 ID(希望这是清楚的)。通过这种方式,过滤器最终用于选择与所有过滤器匹配的一小部分数据库条目。
  • 有时我实际上有 47K 个结果要返回,然后延迟为 2.1 分钟,而查询时间不到 1 秒,这对我来说是 Not Acceptable 。
  • 我明白,通过将多个过滤器组合到一个数据库查询中,我可以大大减少结果的数量。然而,过滤器是由用户选择的(因此组合不受限制),他们可以对不同的数据库表进行连接和检查,最后但并非最不重要的一点是,他们希望查看有关每个过滤器返回多少结果的统计信息。

最佳答案

您查询的 SQL 可以告诉我们一些信息。尝试运行 EXPLAIN SELECT ... 并查看查询计划是什么。检查索引是否被正确使用等。

然而,简单的执行调用和 fetchAll 调用之间的区别可能归结为以下几个因素:

  • 底层驱动程序的性能 - 您使用的是 mysqlnd 驱动程序还是旧版本?
  • 结果集的大小 - 将所有数据加载到数组结构中将占用内存和时间
    • 值得注意的是 PDOStatement->execute 无论如何只返回一个 bool 值

首先,我会确保您已为 PHP 分配了足够的内存和 CPU,并检查 PHP 正在使用的 mysql 驱动程序。它应该是mysqlnd

关于php - PDOStatement::fetchAll() 太慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22811983/

相关文章:

php - NodeJS Oboe 不向 PHP 服务器发送请求正文

mysql - 使用父类(super class)表在数据库中建模继承的性能

sql-server - 测试自定义 ORM 解决方案性能开销 - 如何?

php - 使用 AppServer 的消息为 'could not find driver' 的“PDOException”

php - fatal error : Uncaught PDOException: SQLSTATE[42000]:?

php - 如何在 laravel 中执行此操作,子查询其中计数

php - MYSQL表根据日期自动更新

c++ - 文件创建/删除效率?

php - 警告 : mysql_real_escape_string() [function. mysql-real-escape-string]:拒绝用户访问

php - PDO rowCount() 与 SELECT mysql,为什么一个有效而另一个无效?