PDOStatement :: fetchAll()太慢了

时间:2014-04-02 12:46:41

标签: php performance pdo fetchall

我遇到了一个超级慢的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秒...... !!! 我在这里错过了什么?我可以用什么作为替代品?我用Google搜索并搜索了我无法找到解决方案:(提前致谢!

编辑:fetchAll()的持续时间不仅与返回结果的数量有关,而且与$ aArgs的大小有关。不发送任何参数会使fetchAll()在0.01秒内返回,即使结果为50K!提供execute()调用47K参数使得fetchAll()需要120秒才能运行。但它不是创建导致这个问题的大型查询字符串(顺便说一句,执行(不执行)吗?),因为相同的47K参数,但LIMIT到1K结果只需2.5秒... 如上所述,我已经验证了与使用MySQL控制台相比,EXPLO输出与PDO相同。我也没有看到MySQL努力工作,它是Apache进程(因此PHP)一直在吃CPU。 另外:使用较旧的mysql_ *接口,获取结果需要0.03秒。

背景信息

对于好奇:

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

1 个答案:

答案 0 :(得分:0)

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

然而,简单的执行调用和fetchAll调用之间的区别可能有几个因素:

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

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