mysql - 查询性能优化

标签 mysql performance optimization indexing

我有这个 mysql 查询:

SELECT tbl.userid, tbl.name, tbl.courseid, tbl.fullname, IFNULL(tbl.instance, '-') instance, IFNULL(tbl.activityname, '-') activityname,
    IFNULL(tbl.module, '-') module, IFNULL(tbl.attempt, '-') attempt, IFNULL(tbl.score, '-') score,
    CASE tbl.module WHEN 'quiz' THEN (
        CASE WHEN (tbl.attempt IS NULL AND tbl.score IS NULL) THEN 'NOT YET'
        WHEN (tbl.attempt IS NOT NULL AND tbl.score IS NULL) THEN 'ATTEMPT'
        WHEN (tbl.attempt IS NOT NULL AND tbl.score IS NOT NULL) THEN 'FINISH'
        END)
    WHEN 'scorm' THEN (
        CASE WHEN tbl.attempt IS NULL THEN 'NOT YET'
        ELSE (SELECT `status` FROM mdl_scorm_logs WHERE scormid = tbl.instance AND userid = tbl.userid)
        END)
    ELSE '-'
    END `status`
FROM (
    SELECT tbl1.userid, tbl1.name, tbl1.courseid, tbl1.fullname, tbl2.instance,
        CASE tbl2.module WHEN 'quiz' THEN (SELECT `name` FROM mdl_quiz WHERE id = tbl2.instance AND course = tbl1.courseid)
        WHEN 'scorm' THEN (SELECT `name` FROM mdl_scorm WHERE id = tbl2.instance AND course = tbl1.courseid)
        END activityname
        , tbl2.module, 
        CASE tbl2.module WHEN 'quiz' THEN (SELECT MAX(attempt) FROM mdl_quiz_attempts WHERE quiz = tbl2.instance AND userid = tbl1.userid)
        WHEN 'scorm' THEN (SELECT MAX(attempt) FROM mdl_scorm_scoes_track WHERE scormid = tbl2.instance AND userid = tbl1.userid )
        END attempt,
        (SELECT CONCAT(TRUNCATE(ROUND(gg.finalgrade / gi.grademax * 100, 2), 2), ' %')
        FROM mdl_grade_grades gg
        JOIN mdl_grade_items gi ON gg.itemid = gi.id
        WHERE gg.userid = tbl1.userid AND gi.courseid = tbl1.courseid AND gi.itemname = activityname AND gi.itemtype = 'mod'
            AND gi.itemmodule = tbl2.module AND gi.iteminstance = tbl2.instance) score
    FROM (
        SELECT u.id userid, CONCAT(u.firstname, ' ', u.lastname) `name`, c.id courseid, c.fullname
        FROM mdl_user u
        JOIN mdl_role_assignments ra ON u.id = ra.userid
        JOIN mdl_context co ON ra.contextid = co.id
        JOIN mdl_role r ON ra.roleid = r.id
        JOIN mdl_course c ON co.instanceid = c.id
        JOIN mdl_enrol e ON c.id = e.courseid
        JOIN mdl_user_enrolments ue ON e.id = ue.enrolid AND u.id = ue.userid
        WHERE r.archetype = 'student') tbl1
    LEFT JOIN (
        SELECT cm.course, m.name module, cm.instance FROM mdl_course_modules cm
        JOIN mdl_modules m ON cm.module = m.id
        WHERE m.name IN ('quiz', 'scorm')
        ) tbl2
    ON tbl1.courseid = tbl2.course) tbl
WHERE tbl.userid = '4' AND tbl.courseid = '8'
GROUP BY tbl.courseid, tbl.instance
ORDER BY tbl.name, tbl.fullname, tbl.activityname

使用 EXPLAIN 后的结果:

id  select_type table   type    possible_keys   key key_len ref rows    Extra
1   PRIMARY <derived3>  ALL                 122 Using where; Using temporary; Using filesort
3   DERIVED <derived9>  ALL                 42  
3   DERIVED <derived10> ALL                 23  
10  DERIVED m   range   PRIMARY,mdl_modu_nam_ix mdl_modu_nam_ix 62      2   Using where; Using index
10  DERIVED cm  ref mdl_courmodu_mod_ix mdl_courmodu_mod_ix 8   moodle.m.id 4   
9   DERIVED r   ref PRIMARY,mdl_role_arc_ix mdl_role_arc_ix 92      1   Using where; Using index
9   DERIVED ra  ref mdl_roleassi_rol_ix,mdl_roleassi_con_ix,mdl_roleassi_use_ix mdl_roleassi_rol_ix 8   moodle.r.id 5   
9   DERIVED u   eq_ref  PRIMARY PRIMARY 8   moodle.ra.userid    1   
9   DERIVED co  eq_ref  PRIMARY,mdl_cont_ins_ix PRIMARY 8   moodle.ra.contextid 1   
9   DERIVED e   ref PRIMARY,mdl_enro_cou_ix mdl_enro_cou_ix 8   moodle.co.instanceid    1   Using index
9   DERIVED c   eq_ref  PRIMARY PRIMARY 8   moodle.co.instanceid    1   
9   DERIVED ue  eq_ref  mdl_userenro_enruse_uix,mdl_userenro_enr_ix,mdl_userenro_use_ix mdl_userenro_enruse_uix 16  moodle.e.id,moodle.ra.userid    1   Using index
8   DEPENDENT SUBQUERY  gi  ref PRIMARY,mdl_graditem_itenee_ix,mdl_graditem_cou_ix  mdl_graditem_cou_ix 9   tbl1.courseid   1   Using where
8   DEPENDENT SUBQUERY  gg  eq_ref  mdl_gradgrad_useite_uix,mdl_gradgrad_ite_ix,mdl_gradgrad_use_ix mdl_gradgrad_useite_uix 16  tbl1.userid,moodle.gi.id    1   Using where
7   DEPENDENT SUBQUERY  mdl_scorm_scoes_track   ref mdl_scorscoetrac_usescosco_uix,mdl_scorscoetrac_use_ix,mdl_scorscoetrac_sco_ix  mdl_scorscoetrac_usescosco_uix  16  tbl1.userid,tbl2.instance   6   Using where; Using index
6   DEPENDENT SUBQUERY  mdl_quiz_attempts   ref mdl_quizatte_use_ix,mdl_quizatte_qui_ix mdl_quizatte_qui_ix 8   tbl2.instance   2   Using where
5   DEPENDENT SUBQUERY  mdl_scorm   eq_ref  PRIMARY,mdl_scor_cou_ix PRIMARY 8   tbl2.instance   1   Using where
4   DEPENDENT SUBQUERY  mdl_quiz    eq_ref  PRIMARY,mdl_quiz_cou_ix PRIMARY 8   tbl2.instance   1   Using where
2   DEPENDENT SUBQUERY  mdl_scorm_logs  eq_ref  PRIMARY PRIMARY 16  func,func   1   Using where

有什么优化的想法吗? 谢谢。

最佳答案

天啊。非规范化是处理这种情况的唯一方法。好的,您将优化这个查询。下次,当您必须在单个查询中连接 15 个表时,您会做什么?

您的查询看起来像报告。您应该设计用于报告的数据库。查看以下链接,它可能对您有用。

http://en.wikipedia.org/wiki/Denormalization

http://en.wikipedia.org/wiki/Star_schema

关于mysql - 查询性能优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5631267/

相关文章:

MySQL Slow join - 但并非总是如此,也不是在所有表上

Python 效率/优化项目 Euler #5 示例

javascript - 优化击倒/TKO - Alpha3

java - 计算数组中可被给定查询 k 整除的整数个数

php - 在存储到 mysql 数据库之前压缩文本

php - Mysql Date_Format的多种使用

java - 当使用 HBase 作为 MapReduce 的源时,我可以扩展 TableInputFormatBase 来为每个区域创建多个拆分和多个映射器吗?

mysql使用with语句在太多行上计算不同的数字

php - 突出显示 Mysql 搜索。但 preg_replace 不起作用?

c++ - array[1] 会发生什么