2014-03-05 55 views
1

我有以下各表数据库:优化SQL语句一个大表

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个条目的大型表格时,我的查询窒息并且需要永久运行。是否有另一种查询运行速度更快?我可以优化当前查询以更快运行吗?任何帮助表示赞赏。

+1

500+行构成了一个非常小桌子在我书。特别是如果只有2列。 100万行将是一个大型的桌子。另外,你使用的是mysql还是sqlite? – BobbyScon

+0

这也是我的想法。我认为这个查询可以处理500多行,但它不能。我试图找到重写查询的替代方法,但似乎无法完成。我正在使用sqlite。 – user3385373

+0

您定义了哪些索引? – EJP

回答

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_cpsr_scsr_cs索引;放下所有其他人。

(如果你知道你在做什么,你可以进一步优化器。例如,它看起来好像既不是DISTINCT还是sr_cs指标是必要的。)