我有一个包含以下表格的数据库:
Courses(course varchar(10));
Prerequisite(course varchar(10), prereq varchar(10));
StudentRecord(student varchar(10), course varchar(10), PRIMARY KEY (student, course));
课程包含数据库中的所有课程。先决条件包含给定课程的所有先决条件。 StudentRecord持有所有完成特定课程的学生。
我想出了以下查询,根据他/她已经完成的先决条件找到学生可以学习的课程:
SELECT DISTINCT s.student, c.course from StudentRecord s, Courses c
WHERE NOT EXISTS(SELECT * FROM Prerequisite p where p.course = c.course AND
p.prereq NOT IN(SELECT course from StudentRecord
WHERE student = s.student))
AND NOT EXISTS(SELECT * FROM StudentRecord s2 WHERE
s2.student = s.student AND s2.course = c.course);
此查询执行预期,并根据已完成的先决条件返回学生可以学习的课程列表。但是,当“StudentRecord”是一个包含超过500个条目的大型表时,我的查询会阻塞并永远运行。是否有更快的运行的替代查询?我可以优化当前查询以更快地运行吗?任何帮助表示赞赏。
答案 0 :(得分:0)
如果您不知道要为查询创建哪些索引,找到的一种方法是查看数据库认为最好的索引。
首先,创建索引列的所有可能组合:
CREATE INDEX c_c ON Courses(course);
CREATE INDEX p_c ON Prerequisite(course);
CREATE INDEX p_cp ON Prerequisite(course,prereq);
CREATE INDEX p_p ON Prerequisite(prereq);
CREATE INDEX p_pc ON Prerequisite(prereq,course);
CREATE INDEX sr_s ON StudentRecord(student);
CREATE INDEX sr_sc ON StudentRecord(student,course);
CREATE INDEX sr_c ON StudentRecord(course);
CREATE INDEX sr_cs ON StudentRecord(course,student);
然后查看查询的EXPLAIN QUERY PLAN输出:
> EXPLAIN QUERY PLAN SELECT DISTINCT s.student.....;
0|0|0|SCAN TABLE StudentRecord AS s
0|1|1|SCAN TABLE Courses AS c
0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 1
1|0|0|SEARCH TABLE Prerequisite AS p USING COVERING INDEX p_cp (course=?)
1|0|0|EXECUTE CORRELATED LIST SUBQUERY 2
2|0|0|SEARCH TABLE StudentRecord USING COVERING INDEX sr_sc (student=?)
0|0|0|EXECUTE CORRELATED SCALAR SUBQUERY 3
3|0|0|SEARCH TABLE StudentRecord AS s2 USING COVERING INDEX sr_cs (course=? AND student=?)
0|0|0|USE TEMP B-TREE FOR DISTINCT
因此,您实际上只需要p_cp
,sr_sc
和sr_cs
索引;放弃所有其他人。
(如果您知道自己在做什么,可以进一步优化。例如,看起来DISTINCT和sr_cs
索引都不是必需的。)