我正在寻找一个模型,用于保留一组表中所有记录的最后更新时间戳。一个想法是使用触发器实现它,这样无论记录如何更新,DateLastUpdated列都将保持最新。
给定一个名为Data_Updata的测试表,这是我当前的更新触发器,它确保了 数据已更新。在运行此查看时查看查询执行计划,触发器占用了56%的时间。是否有更有效的触发器/ SQL使用?
ALTER TRIGGER [dbo].[Data_Update]
ON [dbo].[Data_Trigger]
FOR UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE
[Data_Trigger]
SET
DateLastUpdated = GetDate()
FROM
[Data_Trigger] data
JOIN
inserted ON data.DataID = inserted.DataID
END
答案 0 :(得分:4)
[Data_trigger]
和inserted
之间的联接很可能在TABLE SCAN/CLUSTERED INDEX SCAN
表上使用了[Data_trigger]
。
你能做什么?
检查此触发器的缓存计划:
1)首先,运行此查询以查找对象(触发器)的plan_handle
:
SELECT t.name AS TriggerName
,ts.*
FROM sys.dm_exec_trigger_stats ts
INNER JOIN sys.triggers t ON ts.object_id = t.object_id
WHERE ts.database_id = DB_ID()
AND t.name LIKE '%Audit%';
2)其次,找到缓存计划(XML)。例如,如果此触发器的计划句柄为0x050009009A0A677BB8E09C7A000000000000000000000000
,则可以使用此查询来查找缓存计划:
DECLARE @plan_handle VARBINARY(64) = 0x050009009A0A677BB8E09C7A000000000000000000000000;
SELECT *
FROM sys.dm_exec_query_plan(@plan_handle) qp;
如果[Data_trigger]
和inserted
之间的联接对CLUSTERED INDEX SCAN
使用[Data_trigger]
,则您SQL Server 2008
中至少有三个选项:
1)UPDATE STATISTICS
[Data_trigger]
表上的SEEK
:updating statistics causes queries to recompile。执行此操作后,测试触发器并再次检查缓存计划以查看它是否使用JOIN
。
2)或者,您可以使用一个UPDATE
子查询从IN
重写FROM
[Data_Trigger] data
WHERE data.DataID IN (SELECT DataID IN SELECT inserted)
:
SEEK
执行此操作后,测试触发器并再次检查缓存计划,看它是否使用SEEK
。
3)如果未使用FROM
[Data_Trigger] data WITH(FORCESEEK)
JOIN
inserted ON data.DataID = inserted.DataID
运算符,则可以use FORCESEEK
table hint (new in SQL Server 2008
; also see Best Practice Considerations section):
TABLE SCAN
要DataID
尝试在{{1}}列上创建唯一(群集或群集)索引。