Domanda

thanks to all of the help in my last question I have made a ton of progress in my project and have even learned a lot. I was hoping that I could get some help on an issue that I am currently facing with a performance hit. Basically we are working with a database that has a table called "AlertHistory", and this table isn't indexed (i know,...). My goal here is to get the latest entry in the AlertHistory table that relates to the current alertid. My thought here is to use an Outer Join, but this took a massive performance hit on our production server (execution time went from ~20 seconds to ~3minutes).

SELECT
    AllAlerts.AlertID as AlertID,
    Queues.QueueID as QueueID,
    Queues.QueueName as QueueName,
    AllAlerts.ConnectorID as ConnectorID,
    AllAlerts.DeviceID as DeviceID,
    AllAlerts.SituationMessage as Summary,
    AllAlerts.AlertDetail as Detail,
    AllAlerts.Acknowledged as Acknowledged,
    "AcknowledgedBy" =
        CASE
            WHEN AllAlerts.Acknowledged = '1' THEN History.CreatedBy
            WHEN AllAlerts.Acknowledged = '0' THEN ' '
        END,
    AllAlerts.AssignedTo as AssignedTo,
    AllAlerts.ReportedTime as CreatedTime,
    AllAlerts.ClearedTime as ClearedTime

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]

    outer apply (
        select top 1 History.CreatedBy 
        from [ISG_SOI ].[dbo].[AlertHistory] as History
        where History.ColumnName = '73549' and History.AlertID = AllAlerts.AlertID
        order by History.CreatedTime DESC
    ) as History

where Queues.QueueName = 'OCC'

Just to explain the out apply, the ColumnName is a static column that I need to source. This database uses an integer identifier 73549. Of course I could use a 'declare' and declare a variable, but our implementation software wont support that (BOXI).

È stato utile?

Soluzione 2

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

And you may even want to try a join hint
A hash or merge should force that to only be evaluated once
[Advanced Query Tuning Concepts][1]

The next step would be to use that query to create a #temp.
Declare the PK on AlertID as the query optimizer can use that information.

Altri suggerimenti

An option worth trying...

(An attempt to have SQL Server sort the data once, then interrogate it, without using temp tables or indexing the real table.)

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]
inner join
(
    SELECT
        ROW_NUMBER() OVER (PARTITION BY AlertID ORDER BY CreatedTime DESC) AS CreatedOrdinal,
        *
    FROM
        [ISG_SOI ].[dbo].[AlertHistory]
    WHERE
        ColumnName = '73549'
)
    AS History
        ON  History.AlertID        = AllAlerts.AlertID
        AND History.CreatedOrdinal = 1

Thanks to @MatBailie and @Blam for the help with this, it really helped improve the query:

    SELECT
    AllAlerts.AlertID as AlertID,
    Queues.QueueID as QueueID,
    Queues.QueueName as QueueName,
    AllAlerts.ConnectorID as ConnectorID,
    AllAlerts.DeviceID as DeviceID,
    AllAlerts.SituationMessage as Summary,
    AllAlerts.AlertDetail as Detail,
    AllAlerts.Acknowledged as Acknowledged,
    "AcknowledgedBy" = 
        CASE
            WHEN AllAlerts.Acknowledged = '1' THEN ISNULL(History.CreatedBy, '')
            WHEN AllAlerts.Acknowledged = '0' THEN ' '
        END,
    AllAlerts.AssignedTo as AssignedTo,
    DATEADD(HOUR, -5, AllAlerts.ReportedTime) as CreatedTime,
    DATEADD(HOUR, -5, AllAlerts.ClearedTime) as ClearedTime,
    AllAlerts.SvcDeskTicket as TicketID

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 

where Queues.QueueName = 'OCC'
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top