我有一些遗留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)
操作上花费了大量时间(表中存在索引并且它们运行良好)。
如何提高这部分的性能?
答案 0 :(得分:9)
在看到执行计划或表索引之前,我会给出最好的教育猜测。首先,这里有一些值得一读的链接。
showplan operator of the week - 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
语句,这实际上可能导致假脱机操作。没办法绕过那个。