From 4ea7da78282cf4788a48a8a7964e625cb68c1b52 Mon Sep 17 00:00:00 2001 From: Eric Merrill Date: Thu, 26 Feb 2015 19:46:37 -0500 Subject: [PATCH] MDL-47911 gradebook: Improve the performance of set_usedinaggregation This function is called many many times during grade calculation, so it should be as efficient as possible. --- lib/grade/grade_category.php | 53 +++++++++++++++--------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 431f0c7a0f646..46bcf4c3946a7 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -767,6 +767,8 @@ private function aggregate_grades($userid, * Set the flags on the grade_grade items to indicate how individual grades are used * in the aggregation. * + * WARNING: This function is called a lot during gradebook recalculation, be very performance considerate. + * * @param int $userid The user we have aggregated the grades for. * @param array $usedweights An array with keys for each of the grade_item columns included in the aggregation. The value are the relative weight. * @param array $novalue An array with keys for each of the grade_item columns skipped because @@ -779,44 +781,32 @@ private function aggregate_grades($userid, private function set_usedinaggregation($userid, $usedweights, $novalue, $dropped, $extracredit) { global $DB; - // First set them all to weight null and status = 'unknown'. - if ($allitems = grade_item::fetch_all(array('categoryid'=>$this->id))) { - list($itemsql, $itemlist) = $DB->get_in_or_equal(array_keys($allitems), SQL_PARAMS_NAMED, 'g'); + // Reset aggregation to unknown and 0 for all grade items for this user and category. + $params = array('categoryid' => $this->id, 'userid' => $userid); + $itemssql = "SELECT id + FROM {grade_items} + WHERE categoryid = :categoryid"; - $itemlist['userid'] = $userid; + $sql = "UPDATE {grade_grades} + SET aggregationstatus = 'unknown', + aggregationweight = 0 + WHERE userid = :userid + AND itemid IN ($itemssql)"; - $DB->set_field_select('grade_grades', - 'aggregationstatus', - 'unknown', - "itemid $itemsql AND userid = :userid", - $itemlist); - $DB->set_field_select('grade_grades', - 'aggregationweight', - 0, - "itemid $itemsql AND userid = :userid", - $itemlist); - } + $DB->execute($sql, $params); - // Included. + // Included with weights. if (!empty($usedweights)) { // The usedweights items are updated individually to record the weights. foreach ($usedweights as $gradeitemid => $contribution) { - $DB->set_field_select('grade_grades', - 'aggregationweight', - $contribution, - "itemid = :itemid AND userid = :userid", - array('itemid'=>$gradeitemid, 'userid'=>$userid)); - } + $sql = "UPDATE {grade_grades} + SET aggregationstatus = 'used', + aggregationweight = :contribution + WHERE itemid = :itemid AND userid = :userid"; - // Now set the status flag for all these weights. - list($itemsql, $itemlist) = $DB->get_in_or_equal(array_keys($usedweights), SQL_PARAMS_NAMED, 'g'); - $itemlist['userid'] = $userid; - - $DB->set_field_select('grade_grades', - 'aggregationstatus', - 'used', - "itemid $itemsql AND userid = :userid", - $itemlist); + $params = array('contribution' => $contribution, 'itemid' => $gradeitemid, 'userid' => $userid); + $DB->execute($sql, $params); + } } // No value. @@ -844,6 +834,7 @@ private function set_usedinaggregation($userid, $usedweights, $novalue, $dropped "itemid $itemsql AND userid = :userid", $itemlist); } + // Extra credit. if (!empty($extracredit)) { list($itemsql, $itemlist) = $DB->get_in_or_equal(array_keys($extracredit), SQL_PARAMS_NAMED, 'g');