SQL обновление работает, не вставлять - PullRequest
9 голосов
/ 26 апреля 2011

Хорошо, я сделаю все возможное, чтобы описать это. У меня есть SP, который передает в XML и обновляет и вставляет другую таблицу. Это работало вчера. Все, что я изменил сегодня, это загрузка временной таблицы с OPENXML vs xml.nodes. Я даже изменил это, и я все еще получаю эту интересную проблему. У меня есть обновление и вставить в ту же транзакцию. Обновление работает, а затем вставка зависает, без ошибок нет ничего ... происходит 9 минут. Обычно занимает 10 секунд. Нет процессов блокировки в соответствии с master.sys.sysprocesses. Самое смешное, что Select of the Insert не возвращает строк, так как они уже есть в базе данных. Обновление обновлений 72438 в

SQL Server Execution Times:
   CPU time = 1359 ms,  elapsed time = 7955 ms.

ROWS AFFECTED(72438)

У меня нет идей относительно того, что может быть причиной моей проблемы? Разрешения я так не думаю? Пробел я так не думаю, потому что будет возвращена Ошибка?

запросы:

UPDATE [Sales].[dbo].[WeeklySummary]
SET [CountryId] = I.CountryId
    ,[CurrencyId] = I.CurrencyId
    ,[WeeklySummaryType] = @WeeklySummaryTypeId       
    ,[WeeklyBalanceAmt] = M.WeeklyBalanceAmt + I.WeeklyBalanceAmt
    ,[CurrencyFactor] = I.CurrencyFactor
    ,[Comment] = I.Comment
    ,[UserStamp] = I.UserStamp
    ,[DateTimeStamp] = I.DateTimeStamp
FROM 
    [Sales].[dbo].[WeeklySummary] M
INNER JOIN
    @WeeklySummaryInserts I
    ON M.EntityId = I.EntityId
    AND M.EntityType = I.EntityType
    AND M.WeekEndingDate = I.WeekEndingDate
    AND M.BalanceId = I.BalanceId
    AND M.ItemType = I.ItemType
    AND M.AccountType = I.AccountType

и

INSERT INTO [Sales].[dbo].[WeeklySummary]
    ([EntityId]
    ,[EntityType]
    ,[WeekEndingDate]
    ,[BalanceId]
    ,[CountryId]
    ,[CurrencyId]
    ,[WeeklySummaryType]
    ,[ItemType]
    ,[AccountType]
    ,[WeeklyBalanceAmt]
    ,[CurrencyFactor]
    ,[Comment]
    ,[UserStamp]
    ,[DateTimeStamp])
SELECT
    I.[EntityId]
,   I.[EntityType]
,   I.[WeekEndingDate]
,   I.[BalanceId]
,   I.[CountryId]
,   I.[CurrencyId]
,   @WeeklySummaryTypeId
,   I.[ItemType]
,   I.[AccountType]
,   I.[WeeklyBalanceAmt]
,   I.[CurrencyFactor]
,   I.[Comment]
,   I.[UserStamp]
,   I.[DateTimeStamp]
FROM 
    @WeeklySummaryInserts I
LEFT OUTER JOIN
    [Sales].[dbo].[WeeklySummary] M
    ON I.EntityId = M.EntityId
    AND I.EntityType = M.EntityType
    AND I.WeekEndingDate = M.WeekEndingDate
    AND I.BalanceId = M.BalanceId
    AND I.ItemType = M.ItemType
    AND I.AccountType = M.AccountType
WHERE M.WeeklySummaryId IS NULL

UPDATE

Попытка совета здесь работала некоторое время. Я выполняю следующее до вызова хранимой процедуры

UPDATE STATISTICS Sales.dbo.WeeklySummary;
UPDATE STATISTICS Sales.dbo.ARSubLedger;
UPDATE STATISTICS dbo.AccountBalance;
UPDATE STATISTICS dbo.InvoiceUnposted
UPDATE STATISTICS dbo.InvoiceItemUnposted;
UPDATE STATISTICS dbo.InvoiceItemUnpostedHistory;
UPDATE STATISTICS dbo.InvoiceUnpostedHistory;
EXEC sp_recompile N'dbo.proc_ChargeRegister'

По-прежнему останавливается в операторе вставки, который снова вставляет 0 строк.

Ответы [ 2 ]

2 голосов
/ 13 мая 2011

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

ШАГ 1: Ручная обработка набора XML для запускаэто произведет ровно одну вставку без обновлений, так что вы можете вернуться к основам и установить, что код все еще выполняет то, что вы ожидаете, и результат в точности соответствует вашим ожиданиям.Это может показаться глупым или ненужным, но вам действительно нужна эта проверка реальности для начала.

ШАГ 2: Сделайте вручную набор XML, который произведет набор вставок среднего размера, но без обновлений.Исходя из вашего опыта с рутиной, попробуйте найти что-то, что будет работать в течение 3-4 секунд.Возможно, 5000 строк.Это продолжает вести себя как ожидалось?

ШАГ 3: Предполагая, что шаги 1 и 2 проходят легко, следующая наиболее вероятная проблема - РАЗМЕР СДЕЛКИ.Если ваше обновление достигает 74 000 строк в одном операторе, то SQL Server должен выделить ресурсы, чтобы иметь возможность откатить все 74 000 строк в случае сбоя.Как правило, вы должны предполагать, что ресурсы (и время), необходимые для поддержания транзакции, растут в геометрической прогрессии по мере увеличения числа строк.Итак, сделайте вручную еще один набор вставок, который содержит 50 000 строк.Вы должны найти, что это занимает значительно больше времени.Пусть это закончится.Это 10 минут, час?Если это занимает много времени, но завершается, у вас есть проблема с размером транзакции, сервер задыхается, пытаясь отследить все необходимое для отката вставки в случае сбоя.

ШАГ 4: Определите, еслився ваша хранимая процедура работает в рамках одной подразумеваемой транзакции.Если это так, то дело обстоит еще хуже, потому что SQL Server отслеживает все, что требуется для отката как 74 000 обновлений, так и ???вставляет в одну транзакцию.Смотрите эту страницу:

http://msdn.microsoft.com/en-us/library/ms687099(v=vs.85).aspx

ШАГ 5: Если у вас есть одна неявная транзакция, вы можете сделать это либо.A) Отключите это, что может помочь некоторым, но не решит проблему полностью, или B) разбить спрок на два отдельных вызова, один для обновлений, один для вставок, так что по крайней мере два находятся в отдельных транзакциях.

ШАГ 6: Подумайте над "кусками".Это метод, позволяющий избежать взрыва транзакционных издержек.Рассматривая только INSERT, чтобы начать нас, вы помещаете вставку в цикл, который начинает и фиксирует транзакцию внутри каждой итерации и завершается, когда количество затронутых строк равно нулю.INSERT изменен таким образом, что вы извлекаете только первые 1000 строк из источника и вставляете их (число 1000 является произвольным, может оказаться, что 5000 дает лучшую производительность, вам придется немного поэкспериментировать).Как только INSERT воздействует на нулевые строки, больше нет строк, которые нужно обработать, и цикл завершается.

БЫСТРОЕ РЕДАКТИРОВАНИЕ: Система «чанкинга» работает, потому что полная пропускная способность для большого набора строк выглядит как квадратичная.Если вы выполняете INSERT, который влияет на огромное количество строк, общее время обработки всех строк увеличивается.Если, с другой стороны, вы разбиваете его и идете строка за строкой, накладные расходы, связанные с открытием и фиксацией каждого оператора, приводят к общему времени взрыва всех строк.Где-то посередине, когда вы «разбили» по 1 тыс. Строк на оператор, требования к транзакциям минимальны, а издержки на открытие и фиксацию оператора незначительны, а общее время обработки всех строк минимально..

0 голосов
/ 13 мая 2011

У меня была проблема, когда хранимый процесс фактически перекомпилировался в середине работы, потому что он удалял строки из временной таблицы.Моя ситуация не похожа на вашу, но моя была настолько странной, что чтение о ней может дать вам некоторые идеи.

Необъяснимые тайм-ауты SQL Server и прерывистая блокировка

IЯ думаю, что вы должны опубликовать полный сохраненный процесс, потому что проблема не в том, где вы думаете.

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