MDL-42065 core_grade: Modified some grade_item queries for improved performance

* Modified 2 queries in grade_item::depends_on to improve performance
* Added additional unit tests to cover those queries better
This commit is contained in:
Sam Chaffee 2013-09-30 15:27:03 -06:00
parent 56cc9b387e
commit 87a26cc402
3 changed files with 230 additions and 12 deletions

View File

@ -1372,18 +1372,20 @@ class grade_item extends grade_object {
if ($grade_category->aggregatesubcats) {
// return all children excluding category items
$params[] = $this->courseid;
$params[] = '%/' . $grade_category->id . '/%';
$sql = "SELECT gi.id
FROM {grade_items} gi
JOIN {grade_categories} gc ON gi.categoryid = gc.id
WHERE $gtypes
$outcomes_sql
AND gi.categoryid IN (
SELECT gc.id
FROM {grade_categories} gc
WHERE gc.path LIKE ?)";
AND gi.courseid = ?
AND gc.path LIKE ?";
} else {
$params[] = $grade_category->id;
$params[] = $this->courseid;
$params[] = $grade_category->id;
$params[] = $this->courseid;
if (empty($CFG->grade_includescalesinaggregation)) {
$params[] = GRADE_TYPE_VALUE;
} else {
@ -1394,6 +1396,7 @@ class grade_item extends grade_object {
FROM {grade_items} gi
WHERE $gtypes
AND gi.categoryid = ?
AND gi.courseid = ?
$outcomes_sql
UNION
@ -1401,6 +1404,7 @@ class grade_item extends grade_object {
FROM {grade_items} gi, {grade_categories} gc
WHERE (gi.itemtype = 'category' OR gi.itemtype = 'course') AND gi.iteminstance=gc.id
AND gc.parent = ?
AND gi.courseid = ?
AND $gtypes
$outcomes_sql";
}

View File

@ -167,13 +167,13 @@ abstract class grade_base_testcase extends advanced_testcase {
* category structure:
course category
|
+--------+-------------+
| |
unittestcategory1 level1category
|
+--------+-------------+
| |
unittestcategory2 unittestcategory3
+--------+-------------+-----------------------+
| | |
unittestcategory1 level1category aggregatesubcatscategory
| |
+--------+-------------+ +------------+---------------+
| | | |
unittestcategory2 unittestcategory3 unittestcategory5 unittestcategory6
*/
private function load_grade_categories() {
global $DB;
@ -253,6 +253,61 @@ abstract class grade_base_testcase extends advanced_testcase {
$grade_category->path = '/'.$course_category->id.'/'.$grade_category->id.'/';
$DB->update_record('grade_categories', $grade_category);
$this->grade_categories[3] = $grade_category;
$grade_category = new stdClass();
$grade_category->fullname = 'aggregatesubcatscategory';
$grade_category->courseid = $this->course->id;
$grade_category->aggregation = GRADE_AGGREGATE_MEAN;
$grade_category->aggregateonlygraded = 1;
$grade_category->aggregatesubcats = 1;
$grade_category->keephigh = 0;
$grade_category->droplow = 0;
$grade_category->parent = $course_category->id;
$grade_category->timecreated = time();
$grade_category->timemodified = time();
$grade_category->depth = 2;
$grade_category->id = $DB->insert_record('grade_categories', $grade_category);
$grade_category->path = '/'.$course_category->id.'/'.$grade_category->id.'/';
$DB->update_record('grade_categories', $grade_category);
$this->grade_categories[4] = $grade_category;
$grade_category = new stdClass();
$grade_category->fullname = 'unittestcategory5';
$grade_category->courseid = $this->course->id;
$grade_category->aggregation = GRADE_AGGREGATE_MEAN;
$grade_category->aggregateonlygraded = 1;
$grade_category->keephigh = 0;
$grade_category->droplow = 0;
$grade_category->parent = $this->grade_categories[4]->id;
$grade_category->timecreated = time();
$grade_category->timemodified = time();
$grade_category->depth = 3;
$grade_category->id = $DB->insert_record('grade_categories', $grade_category);
$grade_category->path = $this->grade_categories[4]->path.$grade_category->id.'/';
$DB->update_record('grade_categories', $grade_category);
$this->grade_categories[5] = $grade_category;
$grade_category = new stdClass();
$grade_category->fullname = 'unittestcategory6';
$grade_category->courseid = $this->course->id;
$grade_category->aggregation = GRADE_AGGREGATE_MEAN;
$grade_category->aggregateonlygraded = 1;
$grade_category->keephigh = 0;
$grade_category->droplow = 0;
$grade_category->parent = $this->grade_categories[4]->id;
$grade_category->timecreated = time();
$grade_category->timemodified = time();
$grade_category->depth = 3;
$grade_category->id = $DB->insert_record('grade_categories', $grade_category);
$grade_category->path = $this->grade_categories[4]->path.$grade_category->id.'/';
$DB->update_record('grade_categories', $grade_category);
$this->grade_categories[6] = $grade_category;
}
/**
@ -490,6 +545,7 @@ abstract class grade_base_testcase extends advanced_testcase {
$grade_item->iteminfo = 'Manual grade item 10 used for unit testing';
$grade_item->timecreated = time();
$grade_item->timemodified = time();
$grade_item->sortorder = 10;
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[10] = $grade_item;
@ -516,6 +572,107 @@ abstract class grade_base_testcase extends advanced_testcase {
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[11] = $grade_item;
// id = 12
$grade_item = new stdClass();
$grade_item->courseid = $this->course->id;
$grade_item->iteminstance = $this->grade_categories[4]->id;
$grade_item->itemname = 'unittestgradeitemaggregatesubcats';
$grade_item->itemtype = 'category';
$grade_item->gradetype = GRADE_TYPE_VALUE;
$grade_item->needsupdate = true;
$grade_item->grademin = 0;
$grade_item->grademax = 100;
$grade_item->iteminfo = 'Grade item 12 used for unit testing';
$grade_item->timecreated = time();
$grade_item->timemodified = time();
$grade_item->sortorder = 12;
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[12] = $grade_item;
// id = 13
$grade_item = new stdClass();
$grade_item->courseid = $this->course->id;
$grade_item->iteminstance = $this->grade_categories[5]->id;
$grade_item->itemname = 'unittestgradeitemcategory5';
$grade_item->itemtype = 'category';
$grade_item->gradetype = GRADE_TYPE_VALUE;
$grade_item->needsupdate = true;
$grade_item->grademin = 0;
$grade_item->grademax = 100;
$grade_item->iteminfo = 'Grade item 13 used for unit testing';
$grade_item->timecreated = time();
$grade_item->timemodified = time();
$grade_item->sortorder = 13;
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[13] = $grade_item;
// id = 14
$grade_item = new stdClass();
$grade_item->courseid = $this->course->id;
$grade_item->iteminstance = $this->grade_categories[6]->id;
$grade_item->itemname = 'unittestgradeitemcategory6';
$grade_item->itemtype = 'category';
$grade_item->gradetype = GRADE_TYPE_VALUE;
$grade_item->needsupdate = true;
$grade_item->grademin = 0;
$grade_item->grademax = 100;
$grade_item->iteminfo = 'Grade item 14 used for unit testing';
$grade_item->timecreated = time();
$grade_item->timemodified = time();
$grade_item->sortorder = 14;
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[14] = $grade_item;
// Manual grade_item
// id = 15
$grade_item = new stdClass();
$grade_item->courseid = $this->course->id;
$grade_item->categoryid = $this->grade_categories[5]->id;
$grade_item->itemname = 'manual grade_item';
$grade_item->itemtype = 'manual';
$grade_item->itemnumber = 0;
$grade_item->needsupdate = false;
$grade_item->gradetype = GRADE_TYPE_VALUE;
$grade_item->grademin = 0;
$grade_item->grademax = 100;
$grade_item->iteminfo = 'Manual grade item 15 used for unit testing';
$grade_item->timecreated = time();
$grade_item->timemodified = time();
$grade_item->sortorder = 15;
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[15] = $grade_item;
// Manual grade_item
// id = 16
$grade_item = new stdClass();
$grade_item->courseid = $this->course->id;
$grade_item->categoryid = $this->grade_categories[6]->id;
$grade_item->itemname = 'manual grade_item';
$grade_item->itemtype = 'manual';
$grade_item->itemnumber = 0;
$grade_item->needsupdate = false;
$grade_item->gradetype = GRADE_TYPE_SCALE;
$grade_item->grademin = 0;
$grade_item->grademax = 100;
$grade_item->iteminfo = 'Manual grade item 16 used for unit testing';
$grade_item->timecreated = time();
$grade_item->timemodified = time();
$grade_item->sortorder = 16;
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[16] = $grade_item;
// $this->grade_items[17] loaded in load_grade_outcomes() in order to use an outcome id.
}
/**
@ -792,5 +949,27 @@ abstract class grade_base_testcase extends advanced_testcase {
$grade_outcome->id = $DB->insert_record('grade_outcomes', $grade_outcome);
$this->grade_outcomes[] = $grade_outcome;
// Manual grade_item with outcome
// id = 17
$grade_item = new stdClass();
$grade_item->courseid = $this->course->id;
$grade_item->categoryid = $this->grade_categories[6]->id;
$grade_item->itemname = 'manual grade_item';
$grade_item->itemtype = 'manual';
$grade_item->itemnumber = 0;
$grade_item->needsupdate = false;
$grade_item->gradetype = GRADE_TYPE_SCALE;
$grade_item->grademin = 0;
$grade_item->grademax = 100;
$grade_item->iteminfo = 'Manual grade item 16 with outcome used for unit testing';
$grade_item->timecreated = time();
$grade_item->timemodified = time();
$grade_item->outcomeid = $this->grade_outcomes[2]->id;
$grade_item->sortorder = 17;
$grade_item->id = $DB->insert_record('grade_items', $grade_item);
$this->grade_items[17] = $grade_item;
}
}

View File

@ -100,7 +100,7 @@ class core_grade_item_testcase extends grade_base_testcase {
$last_grade_item = end($this->grade_items);
$this->assertEquals($grade_item->id, $last_grade_item->id + 1);
$this->assertEquals(12, $grade_item->sortorder);
$this->assertEquals(18, $grade_item->sortorder);
// Keep our reference collection the same as what is in the database.
$this->grade_items[] = $grade_item;
@ -460,6 +460,10 @@ class core_grade_item_testcase extends grade_base_testcase {
}
protected function sub_test_grade_item_depends_on() {
global $CFG;
$origenableoutcomes = $CFG->enableoutcomes;
$CFG->enableoutcomes = 0;
$grade_item = new grade_item($this->grade_items[1], false);
// Calculated grade dependency.
@ -480,6 +484,37 @@ class core_grade_item_testcase extends grade_base_testcase {
sort($deps, SORT_NUMERIC); // For comparison.
$res = array($this->grade_items[4]->id, $this->grade_items[5]->id);
$this->assertEquals($res, $deps);
$CFG->enableoutcomes = 1;
$origgradeincludescalesinaggregation = $CFG->grade_includescalesinaggregation;
$CFG->grade_includescalesinaggregation = 1;
// Item in category with aggregate sub categories + $CFG->grade_includescalesinaggregation = 1.
$grade_item = new grade_item($this->grade_items[12], false);
$deps = $grade_item->depends_on();
sort($deps, SORT_NUMERIC);
$res = array($this->grade_items[15]->id, $this->grade_items[16]->id);
$this->assertEquals($res, $deps);
// Item in category with aggregate sub categories + $CFG->grade_includescalesinaggregation = 0.
$CFG->grade_includescalesinaggregation = 0;
$grade_item = new grade_item($this->grade_items[12], false);
$deps = $grade_item->depends_on();
sort($deps, SORT_NUMERIC);
$res = array($this->grade_items[15]->id);
$this->assertEquals($res, $deps);
$CFG->grade_includescalesinaggregation = 1;
// Outcome item in category with with aggregate sub categories.
$CFG->enableoutcomes = 0;
$grade_item = new grade_item($this->grade_items[12], false);
$deps = $grade_item->depends_on();
sort($deps, SORT_NUMERIC);
$res = array($this->grade_items[15]->id, $this->grade_items[16]->id, $this->grade_items[17]->id);
$this->assertEquals($res, $deps);
$CFG->enableoutcomes = $origenableoutcomes;
$CFG->grade_includescalesinaggregation = $origgradeincludescalesinaggregation;
}
protected function sub_test_refresh_grades() {