SQL Server 2005表假脱机(懒惰假脱机) - 性能

时间:2012-03-15 13:45:55

标签: sql sql-server-2005

我有一些遗留SQL(SP)

  declare @FactorCollectionId       int;        select  @FactorCollectionId = collectionID from dbo.collection where name = 'Factor'
    declare @changeDate             datetime;   set @changeDate = getDate()
    declare @changeTimeID           int;        set @changeTImeID = convert(int, convert(varchar(8), @changeDate, 112))
    declare @MaxWindowID            int;        select @MaxWindowID = MAX(windowID) from dbo.window

  select distinct @FactorCollectionId, ElementId, T.TimeID, @changeTimeId ChangeTimeID, 1 UserID, @MaxWindowID, 0 ChangeID
                            , null TransactionID, SystemSourceID, changeTypeID, 'R' OlapStatus, Comment, Net0 Delta0, Net0
                            , 1 CreatedBy, 1 UpdatedBy, @changeDate CreatedDate, @changeDate UpdatedDate, 1 CurrentRecord, MeasureTypeID
                from dbo.aowCollectedFact FV
                    inner join dbo.timeView T on T.timeID >= FV.timeID
                where FV.currentRecord = 1                              --is current record
                    and T.CurrentHorizon <> 0                           --Indicator that Time is part of current horizon
                    and FV.collectionID = @FactorCollectionId           --factor collections only
                    and FV.timeID = (select  MAX(timeID)                --latest collected fact timeID for given collectionID and elementID
                                        from    aowCollectedFact FV2
                                        where   FV2.collectionId = @FactorCollectionId
                                            and FV2.elementId = FV.elementID)
                    and (((T.ForecastLevel = 'Month') and (T.FirstDayInMonth = T.Date))     --Date is first of month for monthly customers, or
                            or 
                        ((T.ForecastLevel = 'Quarter')and (T.FirstDayInQuarter = T.Date)))  --Date is first of quarter for quarterly customers
                    and not exists (select  1                                               --Record does not already exist in collected fact view
                                    from    aowCollectedFact FV3                            --  for this factor collection, elementID, and timeID
                                    where   FV3.collectionId = @FactorCollectionId
                                        and FV3.elementID = FV.elementId
                                        and FV3.timeID = T.timeID)

此SQL处理超过200万行。我需要提高它的性能。当我查看执行计划时,我发现在Table Spool (Lazy spool)操作上花费了大量时间(表中存在索引并且它们运行良好)。

如何提高这部分的性能?

1 个答案:

答案 0 :(得分:9)

在看到执行计划或表索引之前,我会给出最好的教育猜测。首先,这里有一些值得一读的链接。

showplan operator of the week - lazy spool

Table spool/Lazy spool

索引:查看您的索引,确保它们全部覆盖您从表格中选择的列。您将希望获得索引中的JOIN和WHERE子句中包含的所有列。 SELECT语句中的所有其他列应该由索引包含或覆盖。

运算符:看看你是否可以摆脱不等于(“&lt;&gt;”)的运算符,而不是单个大于或小于运算符。此声明and T.CurrentHorizon <> 0可以更改为此and T.CurrentHorizon > 0吗?

JOINS :摆脱加入自身之外的表的子查询。例如,此行and FV2.elementId = FV.elementID可能会导致一些问题。鉴于你已经在主查询中进行了GROUPing(DISTINCT),你没有理由不能将它从子查询中转移到dbo.aowCollectedFact FV的JOIN中。

DISTINCT :将其更改为GROUP BY。我没有别的理由,因为这是一个很好的做法,需要两分钟。

最后的注释:上述所有情况的例外情况可能是将最终子查询IF NOT EXISTS作为子查询。如果将其更改为JOIN,则必须是LEFT JOIN...WHERE NULL语句,这实际上可能导致假脱机操作。没办法绕过那个。