0

我最近创建了一个 SQL 触发器来替换我曾经运行的非常昂贵的查询,以减少我的数据库每天执行的更新量。

在执行更新之前,我会检查当天已经发生了多少更新,这通常通过查询来完成:

SELECT COUNT(*) FROM Movies WHERE DateAdded = Date.Now

好吧,我的数据库有超过 100 万条记录,这个查询每分钟运行大约 1-2k,所以你可以明白我为什么要为此采取新方法。

因此,我创建了一个审计表并设置了一个 SQL 触发器,以在 Movie 表上发生任何 INSERT 或 UPDATE 时更新该表。但是我注意到审计表每天有几百个不同步(审计表计数高于电影表中的实际更新)。由于这不会构成一个大问题,我只是好奇可能是什么原因造成的,或者如何进行调试?

SQL触发器:

ALTER TRIGGER [dbo].[trg_Audit]
ON [dbo].[Movies]
AFTER UPDATE, INSERT
AS
BEGIN
    UPDATE Audit SET [count] = [count] + 1 WHERE [date] = CONVERT (date, GETDATE())
    IF @@ROWCOUNT=0
    INSERT INTO audit ([date], [count]) VALUES (GETDATE(), 1)
END

上面的触发器只发生在 Movie 表上的 UPDATE 或 INSERT 之后,并尝试更新 Audit 表中的 count + 1,如果它不存在 (IF @@ROWCOUNT=0),它就会创建它。任何帮助将非常感激!谢谢。

4

2 回答 2

2

像这样的东西应该工作:

create table dbo.Movies (
    A int not null,
    B int not null,
    DateAdded datetime not null
)
go
create view dbo.audit
with schemabinding
as
    select CONVERT(date,DateAdded) as dt,COUNT_BIG(*) as cnt
    from dbo.Movies
    group by CONVERT(date,DateAdded)
go
create unique clustered index IX_MovieCounts on dbo.audit (dt)

这称为索引视图。优点是 SQL Server 负责维护存储在此视图中的数据,而且它总是正确的。

除非您使用的是 Enterprise/Developer 版本,否则您将使用提示查询audit视图:NOEXPAND

SELECT * from audit with (noexpand)

这样做的好处是

a)您现在不必自己编写触发器(SQL Server 实际上确实有一些与幕后触发器非常相似的东西),

b) 它现在可以处理多行插入、更新和删除,并且

c) 您不必编写逻辑来处理更改DateAdded值的更新。

于 2014-02-10T09:53:59.933 回答
1

而不是将计数增加 1,您可能应该将其增加已更改的记录数,例如

UPDATE Audit 
SET [count] = [count] + (SELECT COUNT(*) FROM INSERTED)
WHERE [date] = CONVERT (date, GETDATE())
IF @@ROWCOUNT=0
INSERT INTO audit ([date], [count]) 
VALUES (GETDATE(), (SELECT COUNT(*) FROM INSERTED))
于 2014-02-10T09:43:22.617 回答