SQL2000濫用 join 語句 帶來的悲催后果(查詢效率低下)


問題背景:

給學校的網站添加一個問卷調查系統,新加功能主要包含三張表

Survey 問卷表(用來存儲問卷名)

Survey_Question 問卷問題表(用來存儲問卷問題)

Survey_Answer 問卷答案表(用來存儲問卷的答案)

系統是用ASP來寫的,我應該算是二次開發吧(本人工作經驗尚淺如果名詞表達錯誤請見諒,到現在還是很佩服做這個系統的人,竟然能用ASP寫出一個這么復雜的系統,但維護性。。。真的糾結)

由於本人沒學過ASP。所以一開始還是比較糾結的

最終耗時二個星期的時間完成了以下功能:

1.問卷的添加、修改、刪除

2.問卷問題的添加、修改、刪除

3.開啟問卷調查、關閉問卷調查(每次只允許開啟一張問卷)

4.限制個別專業的學生填寫問卷

5.問卷的統計(包含按專業統計問卷、按系統計問卷、按問題統計問卷、查看不滿意問卷的不滿意原因)PS:問題就出在按專業統計問卷,當然其他統計也應該有類似的問題只是結果較少所以沒有出現這么嚴重的問題。

 (不知道小弟的工作效率怎么樣。。。。)

正題(問題出現):

Survey_Answer表的表結構是

ID   Student_No    SQ_Id(問題ID)  A_Content( 問題答案) A_Reason(不滿意問題的理由)

當時統計各專業問卷數據的時 是想着 東西出來就好了所以寫SQL的時候也沒有太在意。能拼出來就很高興了

當時的SQL 是這么寫的(簡寫)(具體的SQL還是比較復雜的。也可能是我寫復雜了,我在文章結尾會附上完整SQL語句)

Select 系,專業,滿意,不滿意,一般,基本滿意,滿意度  ,

from  (

left jion (從Survey_Answer里查詢出各專業滿意的數量

left join (從Survey_Answer里查詢出各專業不滿意的數量)

。。。。。。。。。。。。))

就這樣一直將各專業的滿意數量、不滿意數量等一個個查出來然后left join  或right join 進去

當時的想法如下圖

將查詢的結果一個個拼進去。

 

操作引發的結果:

當有2000個學生填寫后 survey_answer表的數據達到了2W的量(非常小的數據,一個學生填寫11個問題)

當進行查詢的時候發現查詢專業數據統計時竟然需要40秒到1分鍾的時間,

糾結啊

但是放到SQL2008里面則完全不會出現這樣的問題

一樣的查詢語句,一樣的數據 查詢秒查。(SQL2008真心做了不少優化)

 

解決辦法:

一開始考慮學習原系統的辦法(建立專門建一張表用來存統計數據,然后加一個更新按鈕,點擊更新按鈕就更新數據,否則直接查詢該表的數據)

可是這種方法。。。顯然是很。。。個人認為。。。低級的方案。。

自然不能考慮了。

果斷修改SQL語句,一步步剝離子查詢。然后分析,最終將查詢縮短到了3-5秒

 

具體操作是這樣的

Select 系,專業,滿意,不滿意,一般,基本滿意,滿意度  ,

from 

 (從Survey_Answer里查詢出各專業滿意的數量) as t1,

 (從Survey_Answer里查詢出各專業不滿意的數量)as t2,

......

通過這樣的拼接來查詢

因為有些數據為0,但你又必須查詢出來,所以我才想到了用join 來做的

 

問題分析:

個人分析了下應該是這樣的原因

因為學校有37個系

所以在使用join 語句的時候。。。4種結果(滿意,不滿意,基本滿意、一般)應該會做

37*37*37*37 大約200W次吧。。效率自然低下了

而統計系的時候應該是8*8*8*8 的關系所以還不是特別明顯,只是感覺有點慢

(本人的分析可能是有誤,如果知道正確原因的大牛請指點,小弟萬分感謝)

而用了新的SQL語句后。。

效率只是 “+”的關系了,,自然就快了

 總結:

 小小的總結一下。。。以后寫SQL要注意呀。。。。


------------華麗的分割線-------------

老SQL完整語句:

 

View Code
 1 Select isnull((T5.Satisfaction_Count+T5.BSatisfaction_Count)*1.0/nullif(T5.General_Count+T5. BSatisfaction_Count+T5.UnSatisfaction_Count+T5.Satisfaction_Count,0),0) as lastinfo,
 2 T6.Faculty_Name as Faculty_Name, T5.Subject_Name as Subject_Name, T5. UnSatisfaction_Count as UnSatisfaction_Count , T5.Satisfaction_Count as Satisfaction_Count, T5.BSatisfaction_Count as BSatisfaction_Count, T5.General_Count as General_Count, T5.Survey_Count as Survey_Count 
 3 
 4 from (
 5     select * from Faculty where Faculty.Faculty_Flag=1)as T6
 6     -------------------------t5
 7     left join 
 8       (
 9         Select  [Subject].Subject_Faculty as Faculty_Id, isnull([Subject].Subject_Name,T4.Subject_Name )as Subject_Name, isnull(T4. UnSatisfaction_Count,0)as UnSatisfaction_Count ,  
10         isnull(T4.Satisfaction_Count,0)as Satisfaction_Count,  isnull(T4.BSatisfaction_Count,0)as BSatisfaction_Count, isnull(T4.General_Count,0)as General_Count, isnull(T4.Survey_Count,0)as Survey_Count
11             from [Subject] 
12             -------------------------t4
13 left join  
14 (
15 
16                 Select isnull(Survey.Subject_Name,T3.Subject_Name )as Subject_Name, (T3. UnSatisfaction_Count)  , (T3.Satisfaction_Count) , (T3.BSatisfaction_Count) , (T3.General_Count), Survey.Survey_Count 
17             from ( 
18             select [Subject].Subject_Name as Subject_Name,     count(DISTINCT Survey_Answer.Student_No) as Survey_Count from Student,VClass,[Subject],Survey_Answer,Survey,Survey_Question
19             where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass and  Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id 
20             and  Survey_Answer.Student_No=Student.Student_No and  VClass.VClass_Years='2013'  and  Survey.ID=1 Group by [Subject].Subject_Name
21              ) as Survey
22 -------------------------t3
23 Right join 
24 ( 
25 select isnull(UnSatisfaction.Subject_Name,T2.Subject_Name )as Subject_Name, isnull (UnSatisfaction.UnSatisfaction_Count,0) as UnSatisfaction_Count, T2.Satisfaction_Count, T2.BSatisfaction_Count, T2.General_Count  From (SELECT  [Subject].Subject_Name as Subject_Name, count(Survey_Answer.ID) as UnSatisfaction_Count 
26  from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question
27   where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass and  Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='不滿意' Group by Subject_Name
28    ) as UnSatisfaction
29 ------------------------T2
30  Right join  
31  ( 
32  Select isnull(General. Subject_Name,T1.Subject_Name )as Subject_Name, isnull (General.General_Count,0) as General_Count, T1.Satisfaction_Count, T1.BSatisfaction_Count
33   From (
34   SELECT  [Subject].Subject_Name as Subject_Name, count(Survey_Answer.ID) as General_Count  
35   from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question 
36   where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass and  Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='一般' Group by Subject_Name
37    ) as General
38    
39    
40    -------------------------T1
41  right join  
42  ( 
43  select isnull(BSatisfaction.BSatisfaction_Count,0) as BSatisfaction_Count,  isnull(Satisfaction. Satisfaction_Count,0) as  Satisfaction_Count,  isnull(Satisfaction. Subject_Name,BSatisfaction.Subject_Name )as Subject_Name 
44   from (
45   SELECT  [Subject].Subject_Name as Subject_Name, count(Survey_Answer.ID) as BSatisfaction_Count 
46    from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question 
47    where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass and  Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='基本滿意' Group by Subject_Name
48     ) as BSatisfaction 
49     
50 right join 
51  (
52  SELECT  [Subject].Subject_Name as Subject_Name, count(Survey_Answer.ID) as Satisfaction_Count
53    from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question 
54    where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass and   Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='滿意' Group by Subject_Name 
55    ) as Satisfaction 
56    
57    on Satisfaction.Subject_Name=BSatisfaction.Subject_Name  )as T1 
58    ------------------------------T1end
59    
60     on T1.Subject_Name=General.Subject_Name )as T2 
61     -----------------------------T2END
62     
63      on  T2.Subject_Name=UnSatisfaction.Subject_Name )As T3 
64      
65      ---------------------------------t3end
66      
67      ON T3.Subject_Name=Survey.Subject_Name   )As T4
68      
69      -------------------------t4end
70       ON T4.Subject_Name=[Subject].Subject_Name   )as T5 
71       -------------------------t5end
72       on T5.Faculty_Id=T6.Faculty_Id  

 

 


------------華麗的分割線-------------

新SQL完整語句

 

View Code
 1  select Faculty_Name,T1.Subject_Name,Survey_Count, UnSatisfaction_Count,BSatisfaction_Count ,Satisfaction_Count ,General_Count ,
 2 isnull((Satisfaction_Count+BSatisfaction_Count)*1.0/nullif(General_Count+BSatisfaction_Count+UnSatisfaction_Count+Satisfaction_Count,0),0) as lastinfo
 3  from (
 4 select [Subject].Subject_Name ,isnull(Survey_Count,0)as  Survey_Count
 5 from [Subject]
 6 left join 
 7 
 8 (select [Subject].Subject_Name as Subject_Name, 
 9        count(DISTINCT Survey_Answer.Student_No) as Survey_Count
10         from Student,VClass,[Subject],Survey_Answer,Survey,Survey_Question 
11         where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass
12          and  Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id 
13          and  Survey_Answer.Student_No=Student.Student_No and  VClass.VClass_Years='2013'  
14          and  Survey.ID=1 Group by [Subject].Subject_Name )as T1
15 on T1.Subject_Name=[Subject].Subject_Name
16 )as T1,
17 
18 
19 (select [Subject].Subject_Name ,isnull(UnSatisfaction_Count,0) as UnSatisfaction_Count
20 from [Subject]
21 left join 
22 (SELECT  [Subject].Subject_Name as Subject_Name, count(Survey_Answer.ID) 
23           as UnSatisfaction_Count  from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question 
24           where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass 
25           and  Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No 
26           and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id
27            and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='不滿意' 
28            Group by Subject_Name)as T1
29 on T1.Subject_Name=[Subject].Subject_Name
30 ) as T2,
31 
32 
33 (select [Subject].Subject_Name ,isnull(BSatisfaction_Count,0)  as BSatisfaction_Count
34 from [Subject]
35 left join 
36 (SELECT  [Subject].Subject_Name as Subject_Name, count(Survey_Answer.ID) 
37               as BSatisfaction_Count  from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question
38                where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass
39                 and  Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No 
40                 and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id 
41                 and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='基本滿意' 
42                 Group by Subject_Name )as T1
43 on T1.Subject_Name=[Subject].Subject_Name
44 )as T3,
45 
46 
47 
48 (select [Subject].Subject_Name ,isnull(Satisfaction_Count,0) as Satisfaction_Count
49 from [Subject]
50 left join 
51 (SELECT  [Subject].Subject_Name 
52                 as Subject_Name, count(Survey_Answer.ID) as Satisfaction_Count  
53                 from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question 
54                 where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass
55                  and   Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No
56                   and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id 
57                   and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='滿意' Group by Subject_Name  )as T1
58 on T1.Subject_Name=[Subject].Subject_Name
59 
60 )as T4,
61 
62 
63 
64 (select [Subject].Subject_Name ,isnull(General_Count,0) as General_Count
65 from [Subject]
66 left join 
67 (SELECT  [Subject].Subject_Name as Subject_Name, count(Survey_Answer.ID) 
68             as General_Count  from Student,VClass,Survey_Answer,[Subject],Survey,Survey_Question 
69             where  VClass.VClass_Subject=[Subject].Subject_Id and VClass.VClass_Id=Student.Student_VClass 
70             and  Survey_Answer.Student_No=Student.Student_No and Survey_Answer.Student_No=Student.Student_No 
71             and Survey.ID=Survey_Question.Survey_ID and Survey_Question.ID=Survey_Answer.SQ_Id 
72             and  VClass.VClass_Years='2013'  and  Survey.ID=1 and A_Content='一般' Group by Subject_Name
73   )as T1
74   
75 on T1.Subject_Name=[Subject].Subject_Name
76 
77 )as T5,
78 (select Faculty.Faculty_Name ,Subject_Name
79 from [Subject],Faculty
80 where Faculty.Faculty_Id =[Subject].Subject_Faculty)as T6
81 
82 
83 where T6.Subject_Name=T1.Subject_Name and 
84  T6.Subject_Name=T2.Subject_Name and 
85 T6.Subject_Name=T3.Subject_Name and 
86 T6.Subject_Name=T4.Subject_Name and
87 T6.Subject_Name=T5.Subject_Name


 后記:

問卷調查使用一周后 已經有2300人填寫過了

下面附帶一些統計的效果圖

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM