可以改进此TSQL查询?

时间:2014-11-23 17:37:42

标签: sql-server tsql

我刚才有一个随机问题,下面这个查询开始误入歧途。不确定这是否是一个侥幸,因为我使用此查询创建报告,并在过去一年中每天至少使用它几次。今天早上我接到了我的SQL DBA的电话,告诉我该查询自周四早上开始运行。查询本身通常需要15到30秒才能运行。

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 

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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