2014-08-29 130 views
0

我有一個查詢SQL查詢如下,任何人都可以爲此提出任何優化;我認爲聯盟行動的大部分工作正在進行 - 是否還有其他方法可以獲得相同的結果? 基本上我想查詢UNION的第一部分,如果每條記錄都沒有結果,那麼需要運行第二部分。請幫忙。 :如何優化SQL查詢?

SET dateformat dmy; 

WITH incidentcategory 
    AS (
    SELECT 1 ord, i.IncidentId, rl.Description Category FROM incident i 
     JOIN IncidentLikelihood l ON i.IncidentId = l.IncidentId 
     JOIN IncidentSeverity s ON i.IncidentId = s.IncidentId 
     JOIN LikelihoodSeverity ls ON l.LikelihoodId = ls.LikelihoodId AND s.SeverityId = ls.SeverityId 
     JOIN RiskLevel rl ON ls.RiskLevelId = rl.riskLevelId 

    UNION 

    SELECT 2 ord, i.incidentid, 
       rl.description Category 
     FROM incident i 
       JOIN incidentreportlikelihood l 
        ON i.incidentid = l.incidentid 
       JOIN incidentreportseverity s 
        ON i.incidentid = s.incidentid 
       JOIN likelihoodseverity ls 
        ON l.likelihoodid = ls.likelihoodid 
        AND s.severityid = ls.severityid 
       JOIN risklevel rl 
        ON ls.risklevelid = rl.risklevelid 

       ) , 
ic AS (
     SELECT ROW_NUMBER() OVER (PARTITION BY i.IncidentId ORDER BY (CASE WHEN incidentTime IS NULL THEN GETDATE() ELSE incidentTime END) DESC,ord ASC) rn, 
         i.incidentid, 
         dbo.Incidentdescription(i.incidentid, '', 
         '', 
         '', '') 
           IncidentDescription, 
         dbo.Dateconverttimezonecompanyid(closedtime, 
         i.companyid) 
           ClosedTime, 
         incidenttime, 
         incidentno, 
         Isnull(c.category, '') 
           Category, 
         opencorrectiveactions, 
         reportcompleted, 
         Isnull(classificationcompleted, 0) 
           ClassificationCompleted, 
         Cast ((CASE 
            WHEN closedtime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           IncidentClosed, 
         Cast ((CASE 
            WHEN investigatorfinishedtime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           InvestigationFinished, 
         Cast ((CASE 
            WHEN investigationcompletetime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           InvestigationComplete, 
         Cast ((CASE 
            WHEN investigatorassignedtime IS NULL THEN 0 
            ELSE 1 
           END) AS BIT) 
           InvestigatorAssigned, 
         Cast ((CASE 
            WHEN (SELECT Count(*) 
             FROM incidentinvestigator 
             WHERE incidentid = i.incidentid 
               AND personid = 1588 
               AND tablename = 'AdminLevels') = 0 
           THEN 0 
            ELSE 1 
           END) AS BIT) 
           IncidentInvestigator, 
         (SELECT dbo.Strconcat(osname) 
         FROM (SELECT TOP 10 osname 
           FROM incidentlocation l 
             JOIN organisationstructure o 
              ON l.locationid = o.osid 
           WHERE incidentid = i.incidentid 
           ORDER BY l.locorder) loc) 
           Location, 
         Isnull((SELECT TOP 1 teamleader 
           FROM incidentinvestigator 
           WHERE personid = 1588 
             AND tablename = 'AdminLevels' 
             AND incidentid = i.incidentid), 0) 
           TeamLeader, 
         incidentstatus, 
         incidentstatussearch 
     FROM incident i 
       LEFT OUTER JOIN incidentcategory c 
          ON i.incidentid = c.incidentid 
     WHERE i.isdeleted = 0 
       AND i.companyid = 158 
       AND incidentno <> 0 
       --AND reportcompleted = 1 
       --AND investigatorassignedtime IS NOT NULL 
       --AND investigatorfinishedtime IS NULL 
       --AND closedtime IS NULL 
      ), 
ic2 AS ( 
SELECT * FROM ic WHERE rn=1 
) 
SELECT * FROM ic2 

--WHERE rownumber >= 0 
--  AND rownumber < 0 + 10 
--WHERE ic2.incidentid in(53327,53538) 
--WHERE ic2.incidentid = 53338 

ORDER BY incidentid DESC 

以下是執行計劃我: https://www.dropbox.com/s/50dcpelr1ag4blp/Execution_Plan.sqlplan?dl=0

+4

你**覺得**大部分努力都在聯盟中,但你可以肯定地發現,如果你告訴SSMS向你展示[執行計劃](http://technet.microsoft.com/en-我們/庫/ ms178071%28V = SQL.105%29.aspx)。沒有更多信息,這類問題通常無法回答。模式,索引和/或理想的[sqlfiddle](http://sqlfiddle.com)顯示問題將幫助我們幫助您。 – Dan 2014-08-29 05:15:55

+2

這是一個查詢的問題。 – radpin 2014-08-29 05:18:12

+0

理想情況下,你應該做一個簡單的例子,就像你的情況,並把它放在這裏,而不是給我們整個查詢。 – 2014-08-29 05:23:17

回答

2

有幾個問題:

1)使用UNION ALL而不是UNION ALL,以避免額外的操作來彙總數據。 2)嘗試修改衆多函數調用(例如dbo.Incidentdescription())作爲一個內置表值函數,以便您可以使用CROSS APPLY或OUTER APPLY來引用它。尤其是,如果這些函數再次引用一個表。

3)再次使用CROSS APPLY或OUTER APPLY將子查詢從查詢​​的SELECT部分​​移動到FROM部分。

4)完成上述操作後,再次檢查執行計劃是否有缺失的索引。此外,使用STATISTICS TIME,IO運行查詢以驗證表 被引用的次數是否正確(有時執行計劃會使您的方向錯誤,尤其是涉及函數調用的情況下)...

+0

嘗試了UNION ALL而不是UNION,並用OUTER APPLY替換了LEFT OUTER JOIN - 似乎花費了相同的時間。 – marifrahman 2014-08-29 07:37:24

+0

你可以請建議修改查詢如何將select從select移動到from? – marifrahman 2014-08-29 07:39:55

+0

請提供重寫查詢的執行計劃。 – Lmu92 2014-08-29 15:26:36

0

由於第一個內部查詢生成的ord = 1的行,第二個生成的ord = 2的行,您應該使用UNION ALL而不是UNION。 UNION會過濾掉相同的行,並且由於您永遠不會獲得相同的行,因此使用UNION ALL會更高效。

此外,重寫您的查詢不使用WITH構造。我遇到過非常糟糕的經歷。只需使用常規派生表。在查詢仍然異常緩慢的情況下,嘗試將某些派生表序列化爲臨時表,並改爲查詢臨時表。

+0

你可以分享一個cte(「WITH構造」)比派生表執行效率更低的例子嗎? – Lmu92 2014-08-29 15:25:48

+0

@ Lmu92這裏沒有足夠的空間來提供示例。我遇到的問題通常是CTE,它們很複雜,導致很多行。在某些情況下 - 至少對於性能不佳的SQL05和SQL08 - 優化器失敗並重新生成CTE(或視圖)多次。建議將此CTE(或視圖)「物化」爲臨時表,然後改爲查詢臨時表。其他技巧(SELECT TOP 2147483647 ...)存在,但我不是一個粉絲。在Web上查找「sql server materialized cte」以獲取更多上下文。 – 2014-08-30 09:13:26

0

通過從SELECT除去

(SELECT dbo.Strconcat(osname) 
         FROM (SELECT TOP 10 osname 
           FROM incidentlocation l 
             JOIN organisationstructure o 
              ON l.locationid = o.osid 
           WHERE incidentid = i.incidentid 
           ORDER BY l.locorder) loc) 
           Location, 
         Isnull((SELECT TOP 1 teamleader 
           FROM incidentinvestigator 
           WHERE personid = 1588 
             AND tablename = 'AdminLevels' 
             AND incidentid = i.incidentid), 0) 
           TeamLeader 

嘗試另一種方法。避免在select中使用複雜的函數/子查詢。