Медленное соединение на вставленных / удаленных триггерных таблицах - PullRequest
3 голосов
/ 13 октября 2011

У нас есть триггер, который создает записи аудита для таблицы и объединяет таблицы inserted и deleted, чтобы увидеть, изменились ли какие-либо столбцы.Объединение работало хорошо для небольших наборов, но сейчас я обновляю около 1 миллиона строк, и оно не заканчивается через несколько дней.Я попытался обновить выбранное количество строк с разным порядком величины, и очевидно, что это экспоненциально, что имело бы смысл, если бы таблицы inserted / deleted сканировались для объединения.

Я пыталсясоздайте индекс, но получите ошибку: Cannot find the object "inserted" because it does not exist or you do not have permissions.

Есть ли способ сделать это быстрее?

1 Ответ

4 голосов
/ 13 октября 2011

Вставка во временные таблицы, проиндексированные в соединяющихся столбцах, может улучшить ситуацию, поскольку inserted и deleted не проиндексированы.

Вы можете проверить @@ROWCOUNT внутри триггера, чтобы выполнять эту логику только над некоторым пороговым числом строк, хотя в SQL Server 2008 это может несколько завышать число, если триггер был запущен в результате выполнения оператора MERGE ( Он вернет общее количество строк, на которые влияют все действия MERGE, а не только те, которые относятся к этому конкретному триггеру.

В этом случае вы можете просто сделать что-то вроде SELECT @NumRows = COUNT(*) FROM (SELECT TOP 10 * FROM INSERTED) T, чтобы увидеть, достигнут ли порог.

Сложение

Еще одна возможность, с которой вы можете поэкспериментировать, - это просто обойти триггер для этих больших обновлений. Вы можете использовать SET CONTEXT_INFO, чтобы установить флаг и проверить значение этого внутри триггера. Затем вы можете использовать OUTPUT inserted.*, deleted.*, чтобы получить значения «до» и «после» для строки без необходимости JOIN.

DECLARE @TriggerFlag varbinary(128)
SET @TriggerFlag = CAST('Disabled' AS varbinary(128)) 

SET CONTEXT_INFO @TriggerFlag

UPDATE YourTable
SET Bar = 'X'
OUTPUT inserted.*, deleted.* INTO @T

/*Reset the flag*/
SET CONTEXT_INFO 0x
...