2014-11-23 254 views
0

我剛剛有一個隨機問題,下面的這個查詢開始迷路了。不知道這是否是一種僥倖,因爲我使用此查詢來創建報告,並在過去的一年中每天至少使用過幾次。今天早上,我從我的SQL DBA接到一個電話,告訴我查詢自週四早上開始運行。查詢本身通常需要15 - 30秒才能運行。可能改進此TSQL查詢?

http://i.stack.imgur.com/pMy2d.png enter image description here

SELECT 
AllAlerts.AlertID as AlertID, 
Queues.QueueID as QueueID, 
Queues.QueueName as QueueName, 
AllAlerts.ConnectorID as ConnectorID, 
cast(ISNULL(STUFF ((
    select cast(',' as varchar(max)) + Services.Label 
    from (
     SELECT distinct Services.Label 
     from [ISG_SOI ].[dbo].[SecureServiceCI] as Services 

     inner join [ISG_SOI ].[dbo].[CIRelationship] as Relationship 
     on Relationship.BNodeCIID = AllAlerts.CIID 

     where Services.CIID = Relationship.ServiceCIID 
    ) as Services 
    for xml path ('') 
), 1, 1, ''), '') as CHAR(1000)) as OwnedServices, 
SUBSTRING(AllAlerts.DeviceID, 
    ISNULL(2 + LEN(AllAlerts.DeviceID) - NULLIF(CHARINDEX(',', REVERSE(AllAlerts.DeviceID)), 0), 0), 
    CASE CHARINDEX(':', AllAlerts.DeviceID) WHEN 0 THEN LEN(AllAlerts.DeviceID) + 1 ELSE CHARINDEX(':', AllAlerts.DeviceID) END - 
    ISNULL(2 + LEN(AllAlerts.DeviceID) - NULLIF(CHARINDEX(',', REVERSE(AllAlerts.DeviceID)), 0), 0) 
) AS CIName, 
AllAlerts.DeviceID as DeviceID, 
AllAlerts.SituationMessage as Summary, 
AllAlerts.AlertDetail as Detail, 
AllAlerts.Acknowledged as Acknowledged, 
AllAlerts.UserAttribute5 as Occurrences, 
"AcknowledgedBy" = 
    CASE 
     WHEN AllAlerts.Acknowledged = '1' THEN ISNULL(History.CreatedBy, '') 
     WHEN AllAlerts.Acknowledged = '0' THEN ' ' 
    END, 
AllAlerts.AssignedTo as AssignedTo, 
DATEADD(HOUR, DATEDIFF (HH, GETUTCDATE(), GETDATE()), AllAlerts.ReportedTime) as CreatedTime, 
DATEADD(HOUR,DATEDIFF (HH, GETUTCDATE(), GETDATE()), AllAlerts.ClearedTime) as ClearedTime, 
"Severity" = 
    CASE 
     WHEN AllAlerts.Severity = '4' THEN 'Down' 
     WHEN AllAlerts.Severity = '3' THEN 'Critical' 
     WHEN AllAlerts.Severity = '2' THEN 'Major' 
     WHEN AllAlerts.Severity = '1' THEN 'Minor' 
    END, 
AllAlerts.SvcDeskTicket as TicketID, 
ISNULL(STUFF ((
     select cast('# ' as varchar(max)) + Notes.AnnotationText + '[' + Notes.CreatedBy + ', ' + cast(Notes.CreatedTime as varchar(max)) + ']' 
     from [ISG_SOI ].[dbo].[AlertAnnotation] as Notes 
     where Notes.AlertID = AllAlerts.AlertID 
     for xml path('') 
    ), 1, 1, ''), '') as Notes 

from 
[ISG_SOI ].[dbo].[Alerts] as AllAlerts 

inner join [ISG_SOI ].[dbo].[AlertQueueAssignments] as QA 
    on QA.[AlertID] = AllAlerts.[AlertID] 
inner join [ISG_SOI ].[dbo].[AlertQueues] AS Queues 
    on Queues.[QueueID] = QA.[QueueID] 

left join 
(
    select History.AlertID, max(History.CreatedBy) as CreatedBy 
     from [ISG_SOI ].[dbo].[AlertHistory] as History 
    where History.ColumnName = '73549' 
     and History.Currentvalue = 'true' 
    group by History.AlertID 
) as History 
    on History.AlertID = AllAlerts.AlertID 

回答

1
--try this, variant using temp tables 

--remove calculation from subquery to temp table 
-------------------------------------------------------------------------------- 
IF OBJECT_ID('tempdb..#History') IS NOT NULL 
    DROP TABLE #History 
SELECT History.AlertID , 
     MAX(History.CreatedBy) AS CreatedBy 
INTO #History 
FROM [ISG_SOI ].[dbo].[AlertHistory] AS History 
     INNER JOIN [ISG_SOI ].[dbo].[Alerts] AS AllAlerts 
     ON History.AlertID = AllAlerts.AlertID 
WHERE History.ColumnName = '73549' 
     AND History.Currentvalue = 'true' 
GROUP BY History.AlertID 
------------------------------------------------------------------------------------- 
--XML agregation also is too expensive, reduce time thro removing not required data-- 
------------------------------------------------------------------------------------- 
--1. 
IF OBJECT_ID('tempdb..#Services') IS NOT NULL 
    DROP TABLE #Services 
SELECT DISTINCT 
     Relationship.BNodeCIID , 
     [Services].Label 
INTO #Services 
FROM [ISG_SOI ].[dbo].[SecureServiceCI] AS [Services] 
     INNER JOIN [ISG_SOI ].[dbo].[CIRelationship] AS Relationship 
     ON [Services].CIID = Relationship.ServiceCIID 
     INNER JOIN [ISG_SOI ].[dbo].[Alerts] AS AllAlerts 
     ON Relationship.BNodeCIID = AllAlerts.CIID 
--2. 
IF OBJECT_ID('tempdb..#Notes') IS NOT NULL 
    DROP TABLE #Notes 
SELECT Notes.AlertID , 
     Notes.AnnotationText , 
     Notes.CreatedBy , 
     Notes.CreatedTime 
INTO #Notes 
FROM [ISG_SOI ].[dbo].[AlertAnnotation] AS Notes 
     INNER JOIN [ISG_SOI ].[dbo].[Alerts] AS AllAlerts 
     ON Notes.AlertID = AllAlerts.AlertID 
-------------------------------------------------------------------------------- 

SELECT AllAlerts.AlertID AS AlertID , 
     Queues.QueueID AS QueueID , 
     Queues.QueueName AS QueueName , 
     AllAlerts.ConnectorID AS ConnectorID , 
     CAST(ISNULL(STUFF((SELECT CAST(',' AS VARCHAR(MAX)) 
            + [Services].Label 
          FROM #Services AS [Services] 
          WHERE [Services].BNodeCIID = AllAlerts.CIID 
          FOR 
          XML PATH('') 
         ), 1, 1, ''), '') AS CHAR(1000)) AS OwnedServices , 
     SUBSTRING(AllAlerts.DeviceID, 
        ISNULL(2 + LEN(AllAlerts.DeviceID) 
         - NULLIF(CHARINDEX(',', 
              REVERSE(AllAlerts.DeviceID)), 
            0), 0), 
        CASE CHARINDEX(':', AllAlerts.DeviceID) 
        WHEN 0 THEN LEN(AllAlerts.DeviceID) + 1 
        ELSE CHARINDEX(':', AllAlerts.DeviceID) 
        END - ISNULL(2 + LEN(AllAlerts.DeviceID) 
           - NULLIF(CHARINDEX(',', 
              REVERSE(AllAlerts.DeviceID)), 
             0), 0)) AS CIName , 
     AllAlerts.DeviceID AS DeviceID , 
     AllAlerts.SituationMessage AS Summary , 
     AllAlerts.AlertDetail AS Detail , 
     AllAlerts.Acknowledged AS Acknowledged , 
     AllAlerts.UserAttribute5 AS Occurrences , 
     "AcknowledgedBy" = CASE WHEN AllAlerts.Acknowledged = '1' 
           THEN ISNULL(History.CreatedBy, 
              '') 
           WHEN AllAlerts.Acknowledged = '0' 
           THEN ' ' 
          END , 
     AllAlerts.AssignedTo AS AssignedTo , 
     DATEADD(HOUR, DATEDIFF(HH, GETUTCDATE(), GETDATE()), 
       AllAlerts.ReportedTime) AS CreatedTime , 
     DATEADD(HOUR, DATEDIFF(HH, GETUTCDATE(), GETDATE()), 
       AllAlerts.ClearedTime) AS ClearedTime , 
     "Severity" = CASE WHEN AllAlerts.Severity = '4' 
          THEN 'Down' 
          WHEN AllAlerts.Severity = '3' 
          THEN 'Critical' 
          WHEN AllAlerts.Severity = '2' 
          THEN 'Major' 
          WHEN AllAlerts.Severity = '1' 
          THEN 'Minor' 
        END , 
     AllAlerts.SvcDeskTicket AS TicketID , 
     ISNULL(STUFF((SELECT CAST('# ' AS VARCHAR(MAX)) 
           + Notes.AnnotationText + '[' 
           + Notes.CreatedBy + ', ' 
           + CAST(Notes.CreatedTime AS VARCHAR(MAX)) 
           + ']' 
         FROM  #Notes AS Notes 
         WHERE Notes.AlertID = AllAlerts.AlertID 
        FOR 
         XML PATH('') 
        ), 1, 1, ''), '') AS Notes 
FROM [ISG_SOI ].[dbo].[Alerts] AS AllAlerts 
     INNER JOIN [ISG_SOI ].[dbo].[AlertQueueAssignments] 
     AS QA 
     ON QA.[AlertID] = AllAlerts.[AlertID] 
     INNER JOIN [ISG_SOI ].[dbo].[AlertQueues] AS Queues 
     ON Queues.[QueueID] = QA.[QueueID] 
     LEFT JOIN #History AS History 
     ON History.AlertID = AllAlerts.AlertID 
+0

由於一噸的快速反應。我現在就給這個人一個鏡頭,並會報告回來。謝謝! – 2014-11-24 13:22:59

+0

工作就像一個魅力。查詢時間縮短了10秒,執行路徑更加乾淨 – 2014-11-24 14:30:45

0
--try this, variant using CTE 

--remove calculation from subquery to cte table 
-------------------------------------------------------------------------------- 
; 
WITH History 
      AS (SELECT History.AlertID , 
         MAX(History.CreatedBy) AS CreatedBy 
       FROM  [ISG_SOI ].[dbo].[AlertHistory] AS History 
         INNER JOIN [ISG_SOI ].[dbo].[Alerts] 
         AS AllAlerts 
         ON History.AlertID = AllAlerts.AlertID 
       WHERE History.ColumnName = '73549' 
         AND History.Currentvalue = 'true' 
       GROUP BY History.AlertID 
      ), 
------------------------------------------------------------------------------------- 
--XML agregation also is too expensive, reduce time thro removing not required data-- 
------------------------------------------------------------------------------------- 
--1. 
     [Services] 
      AS (SELECT DISTINCT 
         Relationship.BNodeCIID , 
         [Services].Label 
       FROM  [ISG_SOI ].[dbo].[SecureServiceCI] 
         AS [Services] 
         INNER JOIN [ISG_SOI ].[dbo].[CIRelationship] 
         AS Relationship 
         ON [Services].CIID = Relationship.ServiceCIID 
         INNER JOIN [ISG_SOI ].[dbo].[Alerts] 
         AS AllAlerts 
         ON Relationship.BNodeCIID = AllAlerts.CIID 
      ), 

--2. 
     Notes 
      AS (SELECT Notes.AlertID , 
         Notes.AnnotationText , 
         Notes.CreatedBy , 
         Notes.CreatedTime 
       FROM  [ISG_SOI ].[dbo].[AlertAnnotation] 
         AS Notes 
         INNER JOIN [ISG_SOI ].[dbo].[Alerts] 
         AS AllAlerts 
         ON Notes.AlertID = AllAlerts.AlertID 
      ) 
    -------------------------------------------------------------------------------- 

SELECT AllAlerts.AlertID AS AlertID , 
     Queues.QueueID AS QueueID , 
     Queues.QueueName AS QueueName , 
     AllAlerts.ConnectorID AS ConnectorID , 
     CAST(ISNULL(STUFF((SELECT CAST(',' AS VARCHAR(MAX)) 
            + [Services].Label 
          FROM [Services] 
          WHERE [Services].BNodeCIID = AllAlerts.CIID 
          FOR 
          XML PATH('') 
         ), 1, 1, ''), '') AS CHAR(1000)) AS OwnedServices , 
     SUBSTRING(AllAlerts.DeviceID, 
        ISNULL(2 + LEN(AllAlerts.DeviceID) 
         - NULLIF(CHARINDEX(',', 
              REVERSE(AllAlerts.DeviceID)), 
            0), 0), 
        CASE CHARINDEX(':', AllAlerts.DeviceID) 
        WHEN 0 THEN LEN(AllAlerts.DeviceID) + 1 
        ELSE CHARINDEX(':', AllAlerts.DeviceID) 
        END - ISNULL(2 + LEN(AllAlerts.DeviceID) 
           - NULLIF(CHARINDEX(',', 
              REVERSE(AllAlerts.DeviceID)), 
             0), 0)) AS CIName , 
     AllAlerts.DeviceID AS DeviceID , 
     AllAlerts.SituationMessage AS Summary , 
     AllAlerts.AlertDetail AS Detail , 
     AllAlerts.Acknowledged AS Acknowledged , 
     AllAlerts.UserAttribute5 AS Occurrences , 
     "AcknowledgedBy" = CASE WHEN AllAlerts.Acknowledged = '1' 
           THEN ISNULL(History.CreatedBy, 
              '') 
           WHEN AllAlerts.Acknowledged = '0' 
           THEN ' ' 
          END , 
     AllAlerts.AssignedTo AS AssignedTo , 
     DATEADD(HOUR, DATEDIFF(HH, GETUTCDATE(), GETDATE()), 
       AllAlerts.ReportedTime) AS CreatedTime , 
     DATEADD(HOUR, DATEDIFF(HH, GETUTCDATE(), GETDATE()), 
       AllAlerts.ClearedTime) AS ClearedTime , 
     "Severity" = CASE WHEN AllAlerts.Severity = '4' 
          THEN 'Down' 
          WHEN AllAlerts.Severity = '3' 
          THEN 'Critical' 
          WHEN AllAlerts.Severity = '2' 
          THEN 'Major' 
          WHEN AllAlerts.Severity = '1' 
          THEN 'Minor' 
        END , 
     AllAlerts.SvcDeskTicket AS TicketID , 
     ISNULL(STUFF((SELECT CAST('# ' AS VARCHAR(MAX)) 
           + Notes.AnnotationText + '[' 
           + Notes.CreatedBy + ', ' 
           + CAST(Notes.CreatedTime AS VARCHAR(MAX)) 
           + ']' 
         FROM  Notes 
         WHERE Notes.AlertID = AllAlerts.AlertID 
        FOR 
         XML PATH('') 
        ), 1, 1, ''), '') AS Notes 
FROM [ISG_SOI ].[dbo].[Alerts] AS AllAlerts 
     INNER JOIN [ISG_SOI ].[dbo].[AlertQueueAssignments] 
     AS QA 
     ON QA.[AlertID] = AllAlerts.[AlertID] 
     INNER JOIN [ISG_SOI ].[dbo].[AlertQueues] AS Queues 
     ON Queues.[QueueID] = QA.[QueueID] 
     LEFT JOIN History 
     ON History.AlertID = AllAlerts.AlertID