簡體   English   中英

T-SQL查詢出現意外的性能問題

[英]Unexpected performance issue with T-SQL Query

我有以下T-SQL查詢:

SELECT Wk.WeekID,
       Wk.WeekStart,
       SUM(CASE WHEN NOT(Task.WeekDate IS NULL) THEN 1 ELSE 0 END) AS WeekCount,
       SUM(CASE WHEN NOT(Task.DayDate IS NULL) THEN 1 ELSE 0 END) AS DayCount
FROM tblPerWeek AS Wk
LEFT OUTER JOIN tblPerTask AS Task ON (Task.WeekDate = Wk.WeekStart) 
                                   OR (Task.DayDate BETWEEN Wk.WeekStart AND Wk.WeekEnd)
WHERE (Wk.WeekStart <= @DateEnd) AND (Wk.WeekEnd >= @DateStart)
GROUP BY Wk.WeekID, Wk.WeekStart

tblPerWeek表的結構:

WeekID int
WeekStart date
WeekEnd date

tblPerTask表的結構:

TaskID int
WeekDate date
DayDate date

基本上,查詢計算分配給周(任務WeekCount )或特定的星期(內DayCount )。

tblPerWeek有大約2800條記錄, tblPerTask有大約70000條記錄。

現在, (Task.DayDate BETWEEN Wk.WeekStart AND Wk.WeekEnd)條件存在一些問題/故障:

  • 如果沒有加入此條件,查詢將立即完成
  • 在這種情況下,查詢運行大約需要12秒

有什么收獲? 關於如何使此查詢更快的任何解決方案?

通常,通過使用UNION查詢來解決使用OR的問題。 如果兩組記錄將互斥,請使用UNION ALL,這甚至更快。

SELECT Wk.WeekID,
       Wk.WeekStart,
       SUM(CASE WHEN NOT(Task.WeekDate IS NULL) THEN 1 ELSE 0 END) AS WeekCount,
       SUM(CASE WHEN NOT(Task.DayDate IS NULL) THEN 1 ELSE 0 END) AS DayCount
FROM tblPerWeek AS Wk
LEFT OUTER JOIN tblPerTask AS Task ON Task.WeekDate = Wk.WeekStart
WHERE (Wk.WeekStart <= @DateEnd) AND (Wk.WeekEnd >= @DateStart)
GROUP BY Wk.WeekID, Wk.WeekStart
UNION 
SELECT Wk.WeekID,
       Wk.WeekStart,
       SUM(CASE WHEN NOT(Task.WeekDate IS NULL) THEN 1 ELSE 0 END) AS WeekCount,
       SUM(CASE WHEN NOT(Task.DayDate IS NULL) THEN 1 ELSE 0 END) AS DayCount
FROM tblPerWeek AS Wk
LEFT OUTER JOIN tblPerTask AS Task ON Task.DayDate BETWEEN Wk.WeekStart AND Wk.WeekEnd
WHERE (Wk.WeekStart <= @DateEnd) AND (Wk.WeekEnd >= @DateStart)
GROUP BY Wk.WeekID, Wk.WeekStart

優化器討厭OR

SELECT Wk.WeekID,
       Wk.WeekStart,
       SUM(CASE WHEN TaskW.WeekDate IS NULL THEN 0 ELSE 1 END) AS WeekCount,
       SUM(CASE WHEN TaskD.DayDate  IS NULL THEN 0 ELSE 1 END) AS DayCount
FROM tblPerWeek AS Wk
LEFT OUTER JOIN tblPerTask AS TaskW ON TaskW.WeekDate = Wk.WeekStart                                       
LEFT OUTER JOIN tblPerTask AS TaskD ON TaskD.DayDate BETWEEN Wk.WeekStart AND Wk.WeekEnd
WHERE Wk.WeekStart <= @DateEnd AND Wk.WeekEnd >= @DateStart
GROUP BY Wk.WeekID, Wk.WeekStart

我想你可以做一個計數,因為null為零

SELECT Wk.WeekID, Wk.WeekStart,
       COUNT(TaskW.WeekDate) AS WeekCount,
       COUNT(TaskD.DayDate)  AS DayCount
FROM tblPerWeek AS Wk
LEFT OUTER JOIN tblPerTask AS TaskW ON TaskW.WeekDate = Wk.WeekStart                                       
LEFT OUTER JOIN tblPerTask AS TaskD ON TaskD.DayDate BETWEEN Wk.WeekStart AND Wk.WeekEnd
WHERE Wk.WeekStart <= @DateEnd AND Wk.WeekEnd >= @DateStart
GROUP BY Wk.WeekID, Wk.WeekStart

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM