【问题标题】:Increase performance of trigger in SQL Server提高 SQL Server 中触发器的性能
【发布时间】:2020-07-27 05:17:09
【问题描述】:

我不是数据库专家,但我需要一些帮助,以确保我们用来跟踪表更新的触发器是处理我们的情况的最佳方法,并且可以正常执行。加载触发器后,我们注意到实际业务系统(用户端)的性能有些慢。

背景:我们正在尝试捕获发生交易的日期/时间,以便在我们网站的客户门户上引用它。

理论:触发器监视对“PI”列的更新,如果发生这种情况,它会将数据写入一个表,提供来自与更新相关的其他 2 个表的一些基本信息。

表 1 列

RH.kbranch, RH.kordnum, RH.kcustnum, RH.custsnum, RH.[program]

表 2 列

RD.kbranch, RD.kordnum, RD.kpart

表 3 列(附加触发器的位置)

EQ.kequipnum, EQ.eqpstatus

触发器

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[PICKUPTrigger] 
ON [TEST].[dbo].[equip]
FOR UPDATE
AS  
    IF (SELECT eqpstatus FROM inserted) = 'PI'
    BEGIN
        SET NOCOUNT ON

        INSERT INTO [Workfiles].[dbo].[PickupAudit] ([HHBranch],[HHOrder],[HHCustomer], [HHShipTo], [EquipID], [EQStatus], [PickupNo], [StatusDate])
            SELECT 
                RH.kbranch, RH.kordnum, RH.kcustnum, RH.custsnum, 
                RD.kpart, EQ.eqpstatus, RH.[program], GETDATE()
            FROM 
                TEST.dbo.renthead RH
            JOIN 
                TEST.dbo.rentdetl RD ON RH.kbranch = RD.kbranch 
                                     AND RH.kordnum = RD.kordnum 
                                     AND RH.program NOT LIKE 'OPSS%'
            JOIN 
                TEST.dbo.equip EQ ON EQ.kequipnum = RD.kpart
            WHERE 
                RD.kpart = (SELECT kequipnum FROM inserted);
END

触发器有效,但它似乎会导致问题并降低实际用户体验。感谢您对调整我们所做工作的任何帮助,如果您有任何问题,请随时提问。谢谢。

【问题讨论】:

  • 触发器“有效”,因为它到目前为止只遇到了单行更新。 inserted 可以包含 0、1 或 多个 行。您的代码仅适用于 1。
  • 在修复触发器以处理 2+ 行之后,我将首先查看查询计划。如果他们只是插入一行时确实很慢,我怀疑你缺乏索引。
  • 您应该仅在需要并且了解后果时才使用 3 个(或 4 个部分)名称。一般来说,您应该只使用 2 个部分(模式、对象)名称。如果您(或其他人)想要创建另一个环境(迁移、测试、开发等),那么必须有人更改每 3 个部分的名称。有点担心您的“实际业务系统”使用数据库名称测试 - 但使用别名值得称赞。

标签: sql-server tsql database-trigger


【解决方案1】:

你应该使用明确的joins:

INSERT INTO [Workfiles].[dbo].[PickupAudit]
([HHBranch],[HHOrder],[HHCustomer],[HHShipTo],[EquipID],[EQStatus],[PickupNo],[StatusDate])    
    SELECT RH.kbranch, RH.kordnum, RH.kcustnum, RH.custsnum, RD.kpart, EQ.eqpstatus, RH.[program], GETDATE()
    FROM TEST.dbo.renthead RH JOIN
         TEST.dbo.rentdetl RD
         ON RH.kbranch = RD.kbranch AND
            RH.kordnum = RD.kordnum AND 
            RH.program NOT LIKE 'OPSS%' JOIN
         TEST.dbo.equip EQ
         ON EQ.kequipnum = RD.kpart JOIN
         inserted i
         ON RD.kpart = i.kequipnum;

为了提高性能,您需要在JOINs 中使用的列上的索引,按以下顺序:

  • TEST.dbo.rentdetl(kpart, kbanch, kordnum)
  • TEST.dbo.equip(kequipnum)
  • TEST.dbo.renthead(kbranch, kbanch, program)

【讨论】:

    【解决方案2】:

    缓慢是由连接语句引起的,因为我认为您有时会在触发器操作时连接带有数据或负载的表的重表

    获得更好性能的解决方案是创建“索引视图”而不仅仅是“视图” 并在触发器中使用它,您将看到巨大的影响

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-18
      • 1970-01-01
      相关资源
      最近更新 更多