Skip to content

Commit

Permalink
Improve performance of statistics queries
Browse files Browse the repository at this point in the history
Without this, the many sub-queries in stats calculations that JOIN the
question_references table dont hit any of the indexes on that table. For
sites with large question_references tables - this can be horrible for
performance as it ends up doing a seqscan on that table.

By adding the usingcontextid field, we instead get indexscan's.
  • Loading branch information
aolley committed Jul 15, 2024
1 parent 3c2ae9b commit b2ec47f
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions classes/statistics_calculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,14 @@ private static function get_attempt_stat_joins($cmid, $groupid, $excluderoles =
LEFT JOIN (
SELECT count(*) AS countq, q.createdby AS creator
FROM {studentquiz} sq
JOIN {context} con ON con.instanceid = sq.coursemodule
AND con.contextlevel = ".CONTEXT_MODULE."
-- Get this StudentQuiz question.
JOIN {studentquiz_question} sqq ON sqq.studentquizid = sq.id
JOIN {question_references} qr ON qr.itemid = sqq.id
AND qr.component = 'mod_studentquiz'
AND qr.questionarea = 'studentquiz_question'
AND qr.usingcontextid = con.id
JOIN {question_bank_entries} qbe ON qr.questionbankentryid = qbe.id
JOIN {question_versions} qv ON qv.questionbankentryid = qr.questionbankentryid AND qv.version = (
SELECT MAX(version)
Expand Down Expand Up @@ -159,10 +162,13 @@ private static function get_attempt_stat_joins($cmid, $groupid, $excluderoles =
COUNT(CASE WHEN sqq.state = 0 THEN q.id END) as disapproved,
COUNT(CASE WHEN sqq.state = 1 THEN q.id END) as approved
FROM {studentquiz} sq
JOIN {context} con ON con.instanceid = sq.coursemodule
AND con.contextlevel = ".CONTEXT_MODULE."
JOIN {studentquiz_question} sqq ON sqq.studentquizid = sq.id
JOIN {question_references} qr ON qr.itemid = sqq.id
AND qr.component = 'mod_studentquiz'
AND qr.questionarea = 'studentquiz_question'
AND qr.usingcontextid = con.id
JOIN {question_bank_entries} qbe ON qr.questionbankentryid = qbe.id
JOIN {question_versions} qv ON qv.questionbankentryid = qr.questionbankentryid AND qv.version = (
SELECT MAX(version)
Expand Down Expand Up @@ -193,10 +199,13 @@ private static function get_attempt_stat_joins($cmid, $groupid, $excluderoles =
COUNT(sqv.rate) AS num_rate_perq,
MAX(CASE WHEN sqv.id IS NULL THEN 1 ELSE 0 END) AS question_not_rated
FROM {studentquiz} sq
JOIN {context} con ON con.instanceid = sq.coursemodule
AND con.contextlevel = ".CONTEXT_MODULE."
JOIN {studentquiz_question} sqq ON sqq.studentquizid = sq.id
JOIN {question_references} qr ON qr.itemid = sqq.id
AND qr.component = 'mod_studentquiz'
AND qr.questionarea = 'studentquiz_question'
AND qr.usingcontextid = con.id
JOIN {question_bank_entries} qbe ON qr.questionbankentryid = qbe.id
JOIN {question_versions} qv ON qv.questionbankentryid = qr.questionbankentryid AND qv.version = (
SELECT MAX(version)
Expand Down Expand Up @@ -228,9 +237,12 @@ private static function get_attempt_stat_joins($cmid, $groupid, $excluderoles =
FROM {studentquiz_progress} sp
JOIN {studentquiz_question} sqq ON sp.studentquizquestionid = sqq.id
JOIN {studentquiz} sq ON sq.id = sqq.studentquizid
JOIN {context} con ON con.instanceid = sq.coursemodule
AND con.contextlevel = ".CONTEXT_MODULE."
JOIN {question_references} qr ON qr.itemid = sqq.id
AND qr.component = 'mod_studentquiz'
AND qr.questionarea = 'studentquiz_question'
AND qr.usingcontextid = con.id
JOIN {question_bank_entries} qbe ON qr.questionbankentryid = qbe.id
JOIN {question_versions} qv ON qv.questionbankentryid = qr.questionbankentryid AND qv.version = (
SELECT MAX(version)
Expand All @@ -256,9 +268,12 @@ private static function get_attempt_stat_joins($cmid, $groupid, $excluderoles =
FROM {studentquiz_progress} sp
JOIN {studentquiz_question} sqq ON sp.studentquizquestionid = sqq.id
JOIN {studentquiz} sq ON sq.id = sqq.studentquizid
JOIN {context} con ON con.instanceid = sq.coursemodule
AND con.contextlevel = ".CONTEXT_MODULE."
JOIN {question_references} qr ON qr.itemid = sqq.id
AND qr.component = 'mod_studentquiz'
AND qr.questionarea = 'studentquiz_question'
AND qr.usingcontextid = con.id
JOIN {question_bank_entries} qbe ON qr.questionbankentryid = qbe.id
JOIN {question_versions} qv ON qv.questionbankentryid = qr.questionbankentryid AND qv.version = (
SELECT MAX(version)
Expand Down Expand Up @@ -428,11 +443,14 @@ public static function get_question_stats($cmid, $groupid) {
AVG(rating.avg_rating) AS average_rating,
SUM(CASE WHEN sqq.state = 1 THEN 1 ELSE 0 END) AS questions_approved
FROM {studentquiz} sq
JOIN {context} con ON con.instanceid = sq.coursemodule
AND con.contextlevel = ".CONTEXT_MODULE."
-- Get this StudentQuiz question.
JOIN {studentquiz_question} sqq ON sqq.studentquizid = sq.id
JOIN {question_references} qr ON qr.itemid = sqq.id
AND qr.component = 'mod_studentquiz'
AND qr.questionarea = 'studentquiz_question'
AND qr.usingcontextid = con.id
JOIN {question_bank_entries} qbe ON qr.questionbankentryid = qbe.id
JOIN {question_versions} qv ON qv.questionbankentryid = qr.questionbankentryid AND qv.version = (
SELECT MAX(version)
Expand All @@ -444,11 +462,14 @@ public static function get_question_stats($cmid, $groupid) {
LEFT JOIN (
SELECT q.id AS questionid, COALESCE(AVG(sqr.rate),0) AS avg_rating
FROM {studentquiz} sq
JOIN {context} con ON con.instanceid = sq.coursemodule
AND con.contextlevel = ".CONTEXT_MODULE."
JOIN {studentquiz_question} sqq ON sqq.studentquizid = sq.id
JOIN {question_references} qr ON qr.itemid = sqq.id
JOIN {question_bank_entries} qbe ON qr.questionbankentryid = qbe.id
AND qr.component = 'mod_studentquiz'
AND qr.questionarea = 'studentquiz_question'
AND qr.usingcontextid = con.id
JOIN {question_versions} qv ON qv.questionbankentryid = qr.questionbankentryid AND qv.version = (
SELECT MAX(version)
FROM {question_versions}
Expand Down

0 comments on commit b2ec47f

Please sign in to comment.