【问题标题】:Any Performance Advantages to Consolidating SQL Server Triggers?整合 SQL Server 触发器有哪些性能优势?
【发布时间】:2012-02-28 09:39:12
【问题描述】:

我有一个 SQL Server 表,其中包含 10 个不同的触发器,它们在同一个 INSERT 和 UPDATE 上触发。

将 10 个触发器中的 SQL 合并到一个触发器中是否有任何性能优势?

单个合并触发器与 10 个不同的触发器执行相同的操作,但只会触发一个触发器而不是 10 个。

谢谢!

更新:感谢您的反馈。我更新了我的问题以表明我想知道性能优势。我没有想到“绝对控制秩序”的优势。我知道这些不同的触发器应该在某个时候重构,但我想知道更多关于一个触发器与多个触发器的性能。

【问题讨论】:

  • 这是否意味着您在INSERTEDDELETED 伪表之间也有10 个不同的连接?您不妨只加入一次,尤其是因为这些没有被索引。
  • 如果没有基准测试,我不会回答。你能发布你的触发器在做什么吗?

标签: sql-server triggers


【解决方案1】:

我看到的主要优势是您可以完全控制执行顺序,而您现在还没有。

我可能会建议一种混合方法:1 个触发器调用 10 个存储过程,每个存储过程都封装了一个现有触发器的逻辑。

【讨论】:

    【解决方案2】:

    除了我同意@Joe Stefanelli 之外,还有更多的 SP 可以用于插入、更新和删除触发器。无法理解为什么您会通过任何一种方式获得明显的性能更新。

    10 个触发器,颤抖......

    【讨论】:

      【解决方案3】:

      我同意乔的观点。通过组合成一个触发器,您可以获得:

      • 完全控制订单
      • 在一个地方更好地了解所有操作

      您还可能能够更清楚地看到其中一些逻辑可以组合的地方,并且使用更大的代码段可能能够激发动机来清理它。 10 个触发器听起来很多。每个触发器中正在执行的操作的趋势是什么?是在某处进行审计、更新总数等吗?我确信有些事情可以通过更好的前期逻辑来处理(例如,处理初始插入/更新操作的存储过程、计算列,甚至索引视图,以防止需要执行后 DML 计算)。

      【讨论】:

      • 对以上所有内容都是。我们不是重构这个旧数据库,而是联合它。我需要再添加一个触发器来促进将数据复制到其他地方的过程,我想知道这个新触发器是否会成为压垮骆驼的最后一根稻草。
      【解决方案4】:

      合并触发器可以极大地提升性能。例如,考虑下表、两个触发器和一个更新:

      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 毫秒 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;
      

      同样的更新运行速度是我们的两倍。大惊喜。 ;)

      【讨论】:

      • 一个非常直接的解释。谢谢你。我的大多数触发器都不够兼容,无法利用与您所做的相同的 INSERT 或 UPDATE 语句,但我可能会使用您的一些解决方案和 Aaron 的一些解决方案(调用存储过程)来处理所有这些触发器在一个触发器中分别用于 AFTER INSERT 和 AFTER UPDATE 事件。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-02
      • 1970-01-01
      • 2010-10-01
      相关资源
      最近更新 更多