2015-07-21 3 views
-1

SQL Server 2012, Amazon RDSБесконечная запрос в SQL Server 2012

Это мой простой запрос

update [dbo].[DeliveryPlan] 
set [Amount] = dp.Amount + 
        case when @useAmountColumn = 1 and dbo.ConvertToInt(bs.Amount) > 0 
         then dbo.ConvertToInt(bs.Amount) 
         else @amount 
        end 
from 
    BaseSpecification bs 
join 
    BaseSpecificationStatusType t on (StatusTypeID = t.StatusTypeID) 
join 
    [DeliveryPlan] dp on (dp.BaseSpecificationID = bs.BaseSpecificationID and dp.ItemID = @itemID) 
where 
    bs.BaseID = 130 and t.IsActive = 1 

Это не может быть завершена. Если условие bs.BaseID = 130 (обновление 7000 строк) изменяется для bs.BaseID = 3 (обновление 1000000 строк), оно длится 13 секунд.

Статистические данные являются актуальными, я думаю

В мониторе производительности я вижу использование процессора 5%

Когда я использую зр наблюдать активные соединения и для этого запроса tempdb_allocations 32, tembdb_current - 32, просмотров - 32 000 000, cpu - 860 000 (запрос длится 20 минут)

В чем проблема?

UPDATE: Я добавил некластеризованный индекс для [DeliveryPlan] - по BaseSpecificationID + ItemID и проблема исчезла. К сожалению, я вижу эту проблему каждый день с разными запросами. И проблема исчезает непредсказуемо.

+0

Вы пытались переместить 'dp.ItemID = @ itemID' в предложение WHERE? Я на 90% уверен, что это не поможет, но меня очень интересует результат. – OzrenTkalcecKrznaric

+0

результат тот же –

+0

как насчет индексов на соединенных столбцах? и отфильтрованных столбцов? любой намек из плана запроса? Что такое rowcount таблицы 'BaseSpecificationStatusType'? – Paolo

ответ

0

Вы можете столкнуться с состоянием блокировки для ваших базовых таблиц.

Оптимизация запроса для обновления dp напрямую, чтобы избежать обновления всех строк DeliveryPlan

update dp set [Amount] = dp.Amount + 
    case 
     when @useAmountColumn=1 and dbo.ConvertToInt(bs.Amount)>0 then 
      dbo.ConvertToInt(bs.Amount) 
     else @amount 
    end 
from 
    BaseSpecification bs 
    join BaseSpecificationStatusType t on (bs.StatusTypeID = t.StatusTypeID) 
    join [DeliveryPlan] dp on (dp.BaseSpecificationID = bs.BaseSpecificationID) 
where 
    bs.BaseID = 130 
    and t.IsActive = 1 
    and dp.ItemID = @itemID 
+0

Мне не хватает точки: предлагаемое решение является тем же самым запросом с перемещенным фильтром от 'join' до' where'. уже выполненное изменение, которое не произвело никакого эффекта. – Paolo

+0

@Paolo Обратите внимание на инструкцию после 'UPDATE', оригинальный запрос - это другая таблица' DeliveryPlan' вместо использования 'dp'. Таким образом, обновление * является * обновлением всех строк вместо целевого «ItemID». – Eric

+0

@Paolo Opps Я вижу сейчас, я думал, что это не ОК, не используя псевдоним, но имя таблицы в UPDATE, но я ошибаюсь. – Eric

0

Это будет работать лучше и по-другому, поскольку условия соединения сузит количество строк в первом идти сам , а не ждать выполнения условия where. План выполнения будет другим для обоих (где/без где).

UPDATE dp 
    SET Amount = dp.Amount + CASE 
         WHEN @useAmountColumn = 1 
         AND dbo.ConvertToInt(bs.Amount) > 0 THEN dbo.ConvertToInt(bs.Amount) 
          ELSE @amount 
         END 
    FROM BaseSpecification bs 
    JOIN BaseSpecificationStatusType t ON 
             (bs.StatusTypeID = t.StatusTypeID 
             AND bs.BaseID = 130 
             AND t.IsActive = 1 
             ) 
    JOIN DeliveryPlan dp ON 
          (dp.BaseSpecificationID = bs.BaseSpecificationID 
         AND dp.ItemID = @itemID 
         ); 
+0

Ваш комментарий не является комментарием: следует зайти в ответ. также почему вы предполагаете, что соединение будет работать быстрее?вы уверены, что оптимизатор запросов не будет обращаться с ними одинаково? – Paolo

+0

еще раз, это не комментарий: все подробности о вашем ответе (почему вы предлагаете это, технические детали и т. Д.) Должны идти в ответ, где они могут быть прочитаны сразу без поиска в списке комментариев. завершите свой ответ. – Paolo

0

Если проблема, упомянутая в части обновления, заключается в том, что она приходит и идет случайным образом, это звучит как плохой нюхательный параметр. Когда проблема возникает, вы можете посмотреть в кеш-план, чтобы проверить, выглядит ли план запроса нормально, а если нет, каковы значения, с которыми был создан план (вы можете найти их в самом левом объекте в плане) и для Например, используйте sp_recompile и посмотрите, какой план вы получите в следующий раз.

+0

Я попытался переопределить параметры в sp, чтобы изменить этот плохой параметр sniffing, который является результатом устаревшей статистики, как я знаю. И статистика была хорошей. –

+1

@MihailKatrikh Параметр sniffing может произойти, даже если статистика на 100% точна, и ваши данные могут быть такими, что определенным идентификаторам нужен другой план, чем другие. Глядя на планы, когда производительность плоха, должна дать вам представление о том, что происходит –