Problem/Motivation
In #3174662: Encapsulate \PDOStatement instead of extending from it a PDO statement wrapper was introduced. The getIterator()
method represents a performance regression relative to earlier versions of Drupal 8/9.
Previously if you did a foreach ($statement as $row) {}
the PDO statement would fetch a single result from the database in each loop keeping memory consumption to a minimum.
Now, the getIterator()
method fetches all results and constructs an ArrayIterator. For a large query site, this is large use of PHP memory.
Steps to reproduce
Compare memory usage before/after this change.
Proposed resolution
See, the API changes.
Remaining tasks
Add patch and tests.
User interface changes
n/a
API changes
- Introduce a
Drupal\Core\Database\StatementWrapperIterator
implementing \Iterator instead of \IteratorAggregate so that iteration on the statement object is kept in sync with the underlying client statement resultset cursor (net of the usage of PDO::MYSQL_ATTR_USE_BUFFERED_QUERY which is a PDO-only feature, other drivers do not necessarily have that, see #45 and #47). - Let core MySql and PostgreSql database drivers implement the new class.
- Deprecate the class
Drupal\Core\Database\StatementWrapper
for removal in D11.
Data model changes
n/a