From 17da93d42bcb26b8ac770d1a52142ed1dc0d3620 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Thu, 8 Aug 2019 14:03:41 +0800 Subject: [PATCH] MDL-66614 pgsql DML: Update get_records_sql to consume less memory This is a backport of MDL-66327. It's more memory efficient to use `pg_fetch_assoc` for each row than to call `pg_fetch_all` and release memory immediately. This is because we can treat the assoc fetch like an iterator and it only fetches the current record into memory one at a time, whilst the all fetch fetches all records and never unsets them. Attempting to unset them is extremely time consuming. --- lib/dml/pgsql_native_moodle_database.php | 30 ++++++++++-------------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/lib/dml/pgsql_native_moodle_database.php b/lib/dml/pgsql_native_moodle_database.php index 97d94905ff9..d894b366070 100644 --- a/lib/dml/pgsql_native_moodle_database.php +++ b/lib/dml/pgsql_native_moodle_database.php @@ -842,8 +842,7 @@ class pgsql_native_moodle_database extends moodle_database { * @return array of objects, or empty array if no records were found * @throws dml_exception A DML specific exception is thrown for any errors. */ - public function get_records_sql($sql, array $params=null, $limitfrom=0, $limitnum=0) { - + public function get_records_sql($sql, array $params = null, $limitfrom = 0, $limitnum = 0) { list($limitfrom, $limitnum) = $this->normalise_limit_from_num($limitfrom, $limitnum); if ($limitnum) { @@ -868,24 +867,19 @@ class pgsql_native_moodle_database extends moodle_database { } } - $rows = pg_fetch_all($result); - pg_free_result($result); - - $return = array(); - if ($rows) { - foreach ($rows as $row) { - $id = reset($row); - if ($blobs) { - foreach ($blobs as $blob) { - $row[$blob] = ($row[$blob] !== null ? pg_unescape_bytea($row[$blob]) : null); - } + $return = []; + while ($row = pg_fetch_assoc($result)) { + $id = reset($row); + if ($blobs) { + foreach ($blobs as $blob) { + $row[$blob] = ($row[$blob] !== null ? pg_unescape_bytea($row[$blob]) : null); } - if (isset($return[$id])) { - $colname = key($row); - debugging("Did you remember to make the first column something unique in your call to get_records? Duplicate value '$id' found in column '$colname'.", DEBUG_DEVELOPER); - } - $return[$id] = (object)$row; } + if (isset($return[$id])) { + $colname = key($row); + debugging("Did you remember to make the first column something unique in your call to get_records? Duplicate value '$id' found in column '$colname'.", DEBUG_DEVELOPER); + } + $return[$id] = (object) $row; } return $return;