我遇到了一个非常缓慢的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)
好的,认真地说?我怎么可以在MySQL控制台中在不到0.1秒的时间内获得我的结果,但是PHP需要2.5秒才能获取那1000个结果并将其放入一个简单的数组中呢?来吧,一个简单的for循环逐个将1000个数字放入数组中只需要0.001秒... !!!
我错过了什么?我可以使用什么替代方案?我已经谷歌搜索了一遍,但是找不到解决方案:( 提前致谢!
编辑:fetchAll()的持续时间不仅与返回的结果数量有关...而且与$aArgs的大小有关。不发送参数使得fetchAll()在0.01秒内返回,即使有50K的结果!向execute()调用提供47K个参数使得fetchAll()需要120秒才能运行。但它不是创建大查询字符串导致这种情况(顺便问一下,execute()会做到这一点吗?),因为相同的47K参数,但是限制为1K个结果只需要2.5秒...
如建议所述,我已经验证了PDO与使用MySQL控制台的EXPLAIN输出是相同的。我也没有看到MySQL在努力工作,而是Apache进程(因此是PHP)在占用CPU。
另外:使用较旧的mysql_*接口,结果的提取只需要0.03秒。
背景信息
对于好奇心:
- 这是一个本地MySQL 5.5数据库,因此不是远程服务器。
- PHP版本:5.4.4。
- 在这种情况下,系统中有一些过滤器(一个过滤器=一个数据库查询),按用户喜欢的顺序运行,在每个过滤器运行时都会传递前一个过滤器运行的匹配条目的ID,并且它应该返回剩余匹配条目的ID(希望这很清楚)。通过这种方式,过滤器用于最终选择与所有过滤器匹配的数据库条目的小子集。
- 有时我确实有要返回47K个结果的情况,然后延迟为2.1分钟,而查询时间少于1秒,这在我的情况下是不可接受的。
- 我知道我可以通过将几个过滤器合并为一个数据库查询来大大降低结果数。但是,过滤器由用户选择(因此无限组合),它们可以在不同的数据库表上进行联接和检查,并且最后但并非最不重要的是,他们希望看到每个过滤器返回多少结果的统计数据。