I'm running into a super slow PDOStatement::fetchAll() that is just driving me nuts. My query is running in less than 0.1 seconds. Also in the MySQL terminal, I get my output on my screen in less than 0.1 seconds. But running fetchAll() on the PDOStatement takes 2.5 seconds.
// $_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? Come on, a simple for loop putting 1000 numbers in an array one by one takes 0.001 seconds...!!! 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. Sending no arguments makes fetchAll() return in 0.01 seconds, even with with 50K results! Feeding the execute() call 47K arguments makes fetchAll() then take 120 seconds to run. 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. I also don't see MySQL working hard, it's the Apache process (thus PHP) that's eating CPU for all this time. ALSO: using the older mysql_* interface, the fetching of the results takes 0.03 seconds.
Background info
For the curious:
- It's a local MySQL 5.5 database, so not a remote server.
- PHP version: 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). 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.
- 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.