简体   繁体   English

PDOStatement :: fetchAll()太慢了

[英]PDOStatement::fetchAll() is too slow

I'm running into a super slow PDOStatement::fetchAll() that is just driving me nuts. 我遇到了一个超级慢的PDOStatement :: fetchAll(),这让我疯狂。 My query is running in less than 0.1 seconds. 我的查询运行时间不到0.1秒。 Also in the MySQL terminal, I get my output on my screen in less than 0.1 seconds. 同样在MySQL终端中,我在不到0.1秒的时间内在屏幕上显示输出。 But running fetchAll() on the PDOStatement takes 2.5 seconds. 但是在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;

This outputs: 这输出:

float(0.0612)
float(2.58708)

OK, seriously? 好的,认真的? How can I get my results in the MySQL console in less than 0.1 seconds, but PHP takes 2.5 seconds to fetch those 1000 results and put it in a simple array? 如何在不到0.1秒的时间内在MySQL控制台中获得我的结果,但PHP需要2.5秒才能获取这1000个结果并将其放入一个简单的数组中? Come on, a simple for loop putting 1000 numbers in an array one by one takes 0.001 seconds...!!! 来吧,一个简单的for循环将1000个数字逐个放入数组中需要0.001秒...... !!! What am I missing here? 我在这里错过了什么? What can I use as an alternative? 我可以用什么作为替代品? I've googled and searched and I can't find a solution :( Thanks in advance! 我用谷歌搜索和搜索,我找不到解决方案:(提前谢谢!

EDIT: Not only is the duration of the fetchAll() related to the number of returned results... but also related to the size of $aArgs. 编辑:fetchAll()的持续时间不仅与返回结果的数量有关,而且还与$ aArgs的大小有关。 Sending no arguments makes fetchAll() return in 0.01 seconds, even with with 50K results! 不发送任何参数会使fetchAll()在0.01秒内返回,即使结果为50K! Feeding the execute() call 47K arguments makes fetchAll() then take 120 seconds to run. 提供execute()调用47K参数使得fetchAll()需要120秒才能运行。 But it's not the creation of the large query string that causes this (doesn't execute() do that by the way?), because the same 47K arguments, but a LIMIT to 1K results takes only 2.5 seconds... As suggested, I've verified that the EXPLAIN output is the same for PDO versus using the MySQL console. 但这不是创建大型查询字符串导致这种情况(顺便说一下,执行()不执行吗?),因为相同的47K参数,但LIMIT到1K结果只需2.5秒......如建议的那样,我已经验证了与使用MySQL控制台相比,EXPLO输出与PDO相同。 I also don't see MySQL working hard, it's the Apache process (thus PHP) that's eating CPU for all this time. 我也没有看到MySQL努力工作,这是Apache进程(因此PHP)一直在吃CPU。 ALSO: using the older mysql_* interface, the fetching of the results takes 0.03 seconds. 另外:使用较旧的mysql_ *接口,获取结果需要0.03秒。

Background info 背景信息

For the curious: 对于好奇:

  • It's a local MySQL 5.5 database, so not a remote server. 它是本地MySQL 5.5数据库,因此不是远程服务器。
  • PHP version: 5.4.4. PHP版本:5.4.4。
  • The use case here, is that there is a number of filters in the system (one filter = one database query), run in a user's favorite order, where each filter gets fed the IDs of the matching entries from the previous filter run, and it should return the IDs of the remaining matching entries (hope this is clear). 这里的用例是,系统中有许多过滤器(一个过滤器=一个数据库查询),以用户最喜欢的顺序运行,每个过滤器从前一个过滤器运行中获取匹配条目的ID,并且它应该返回剩余匹配条目的ID(希望这是明确的)。 In this way, the filters are used to, in the end, select a small subset of database entries that match all filters. 通过这种方式,过滤器最终用于选择与所有过滤器匹配的小数据库条目子集。
  • Some times I actually have 47K results to return, and then the delay is 2.1 minutes while the query takes less than 1 second, not acceptable in my case. 有时我实际上有47K的结果返回,然后延迟是2.1分钟,而查询需要不到1秒,在我的情况下是不可接受的。
  • I understand that I could drastically lower the number of results by combining several filters into one database query. 我知道通过将多个过滤器组合到一个数据库查询中,我可以大大降低结果数量。 However, the filters are selected by users (so unlimited combinations), they can have joins and checks on different database tables, and last but not least, they want to see statistics on how many results each filter returns. 但是,过滤器由用户选择(因此无限制组合),它们可以在不同的数据库表上进行连接和检查,最后但并非最不重要的是,他们希望查看每个过滤器返回的结果数量的统计信息。

Your query's SQL could tell us a bit. 您的查询的SQL可以告诉我们一些。 Try running an EXPLAIN SELECT ... and seeing what the query plan is. 尝试运行EXPLAIN SELECT ...并查看查询计划是什么。 Check that indexes are being used properly, etc. 检查索引是否正确使用等。

However the difference between a simple execute call and a fetchAll call is probably down to a few factors: 但是,简单执行调用和fetchAll调用之间的区别可能有以下几个因素:

  • the performance of the underlying driver - are you using the mysqlnd driver, or a legacy version? 底层驱动程序的性能 - 您使用的是mysqlnd驱动程序还是旧版本?
  • the size of the result set - loading all the data in to array structures will take memory and time 结果集的大小 - 将所有数据加载到数组结构中将占用内存和时间
    • it's worth noting that PDOStatement->execute only returns a boolean value anyway 值得注意的是PDOStatement->execute只返回一个布尔值

In the first instance I'd make sure you've got enough memory and CPU allocated to PHP, and check the mysql driver that PHP is using. 在第一个例子中,我确保你已经有足够的内存和CPU分配给PHP,并检查PHP正在使用的mysql驱动程序。 It should be mysqlnd . 它应该是mysqlnd

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM