2014-03-05 88 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指標是必要的。)