Консолидация триггеров может значительно повысить производительность. Например, рассмотрим следующую таблицу, два триггера и обновление:
CREATE TABLE dbo.TriggerTest(ID INT NOT NULL PRIMARY KEY,
s INT NOT NULL)
GO
INSERT INTO dbo.TriggerTest(ID, s)
SELECT n, 1 FROM dbo.Numbers
WHERE n BETWEEN 1 AND 100000;
GO
CREATE TRIGGER TriggerTestNoSignChange
ON dbo.TriggerTest
AFTER UPDATE
AS
BEGIN
IF EXISTS(SELECT * FROM INSERTED AS i JOIN DELETED AS d
ON i.id = d.id WHERE sign(i.s)*sign(d.s)<0)
BEGIN
RAISERROR('s cannot change sign', 16, 1);
ROLLBACK ;
END
END
GO
CREATE TRIGGER TriggerTestNoBigChange
ON dbo.TriggerTest
AFTER UPDATE
AS
BEGIN
IF EXISTS(SELECT * FROM INSERTED AS i JOIN DELETED AS d
ON i.id = d.id WHERE ABS(i.s - d.s)>5)
BEGIN
RAISERROR('s cannot change by more than 5', 16, 1);
ROLLBACK ;
END
END
GO
UPDATE dbo.TriggerTest SET s=s+1
WHERE ID BETWEEN 1 AND 1000;
Это обновление использует 1671 мс ЦП и 4M чтения. Давайте объединим два триггера и повторно запустим обновление:
DROP TRIGGER TriggerTestNoSignChange;
DROP TRIGGER TriggerTestNoBigChange;
GO
CREATE TRIGGER TriggerTestNoBigChangeOrSignChange
ON dbo.TriggerTest
AFTER UPDATE
AS
BEGIN
IF EXISTS(SELECT * FROM INSERTED AS i JOIN DELETED AS d
ON i.id = d.id WHERE sign(i.s)*sign(d.s)<0 OR ABS(i.s - d.s)>5)
BEGIN
RAISERROR('s cannot change sign or change by more than 5', 16, 1);
ROLLBACK ;
END
END
GO
UPDATE dbo.TriggerTest SET s=s+1
WHERE ID BETWEEN 1 AND 1000;
Это же обновление работает вдвое быстрее. Большой сюрприз. ;)