我有一个SQL Server表,其中包含10个不同的触发器,它们在相同的INSERT和UPDATE上触发。
将10个触发器中的SQL整合到单个触发器中是否具有性能优势?
单个合并的触发器将与10个不同的触发器做同样的事情,但只有一个触发器将被激发,而不是10个。
谢谢!
更新:感谢你的反馈。我更新了我的问题,以表明我想知道性能优势。我没有想到“绝对控制顺序”的优势。我知道这些不同的触发器应该在某个时候重构,但我更想知道一个触发器与多个触发器的性能。
发布于 2012-02-07 10:54:11
整合触发器可以带来巨大的性能提升。例如,考虑下表、两个触发器和一个update:
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;
此更新使用1671ms CPU和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;
相同的更新速度是我们的两倍。大吃一惊。;)
发布于 2012-02-07 06:22:24
我看到的主要优点是您将完全控制执行的顺序,这是您现在所不具备的。
我可能会建议一种混合方法:1个触发器调用10个存储过程,每个过程封装一个现有触发器的逻辑。
发布于 2012-02-07 06:40:00
我同意乔的观点。通过组合成一个触发器,您可以获得:
您还可能能够更清楚地看到这些逻辑可以组合在一起的地方,并且使用更大的代码段可能能够调用动机来清理它。10个触发器听起来很多。在每个触发器中执行的操作的趋势是什么?是在做审计,还是在某处更新总数,等等?我确信有一些事情可以通过更好的前期逻辑来处理(例如,处理初始插入/更新操作的存储过程、计算列,甚至是索引视图,以避免需要执行DML之后的计算)。
https://stackoverflow.com/questions/9168146
复制相似问题