SQL Server 2005 Table Spool (Ленивый спул) - производительность - PullRequest
5 голосов
/ 15 марта 2012

У меня есть устаревший 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 обрабатывает более 2 миллионов строк. Мне нужно улучшить его производительность. Когда я смотрю на план выполнения, я обнаруживаю, что много времени тратится на операцию Table Spool (Lazy spool) (индексы существуют в таблицах и работают хорошо).

Как улучшить производительность этой части?

1 Ответ

9 голосов
/ 15 марта 2012

Перед тем, как увидеть план выполнения или табличные индексы, я дам наиболее образованные догадки. Во-первых, вот пара ссылок, которые стоит прочитать.

оператор showplan недели - ленивая шпуля

Катушка стола / Ленивая шпуля

INDEXING : посмотрите на ваши индексы, чтобы убедиться, что все они охватывают столбцы, которые вы выбираете из таблиц. Вы захотите получить все столбцы, включенные в предложения JOINs и WHERE в индексах. Все остальные столбцы, которые есть в инструкциях SELECT, должны быть включены или включены в индекс.

ОПЕРАТОРЫ : посмотрите, сможете ли вы избавиться от операторов, не равных ("<>"), в пользу одного оператора, большего или меньшего, чем оператор. Может ли это утверждение and T.CurrentHorizon <> 0 быть изменено на это and T.CurrentHorizon > 0?

JOINS : избавиться от подзапросов, которые присоединяются к таблицам вне себя. Например, эта строка and FV2.elementId = FV.elementID может вызывать некоторые проблемы. Нет причины, по которой вы не можете переместить это из подзапроса в JOIN на dbo.aowCollectedFact FV, учитывая, что вы уже группируете (DISTINCT) в основном запросе.

DISTINCT : измените его на GROUP BY. У меня нет другой причины, кроме как, потому что это хорошая практика и занимает две минуты.

ПОСЛЕДНЕЕ ПРИМЕЧАНИЕ : Исключением из всего вышеперечисленного может быть оставление последнего подзапроса, IF NOT EXISTS, в качестве подзапроса. Если вы измените его на JOIN, это будет оператор LEFT JOIN...WHERE NULL, который на самом деле может вызвать операции буферизации. Нет лучшего способа обойти это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...