我有一个简单的查询更新表(30列和大约150 000行)。
例如:
UPDATE tblSomeTable set F3 = @F3 where F1 = @F1
此查询将影响约2500行。
tblSomeTable有一个触发器:
ALTER TRIGGER [dbo].[trg_tblSomeTable]
ON [dbo].[tblSomeTable]
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
declare @operationType nvarchar(1)
declare @createDate datetime
declare @UpdatedColumnsMask varbinary(500) = COLUMNS_UPDATED()
-- detect operation type
if not exists(select top 1 * from inserted)
begin
-- delete
SET @operationType = 'D'
SELECT @createDate = dbo.uf_DateWithCompTimeZone(CompanyId) FROM deleted
end
else if not exists(select top 1 * from deleted)
begin
-- insert
SET @operationType = 'I'
SELECT @createDate = dbo..uf_DateWithCompTimeZone(CompanyId) FROM inserted
end
else
begin
-- update
SET @operationType = 'U'
SELECT @createDate = dbo..uf_DateWithCompTimeZone(CompanyId) FROM inserted
end
-- log data to tmp table
INSERT INTO tbl1
SELECT
@createDate,
@operationType,
@status,
@updatedColumnsMask,
d.F1,
i.F1,
d.F2,
i.F2,
d.F3,
i.F3,
d.F4,
i.F4,
d.F5,
i.F5,
...
FROM (Select 1 as temp) t
LEFT JOIN inserted i on 1=1
LEFT JOIN deleted d on 1=1
END
如果我执行更新查询,我会超时。
如何优化逻辑以避免超时?
谢谢。
答案 0 :(得分:4)
此查询:
SELECT *
FROM (
SELECT 1 AS temp
) t
LEFT JOIN
INSERTED i
ON 1 = 1
LEFT JOIN
DELETED d
ON 1 = 1
将从2500 ^ 2 = 6250000
和INSERTED
的笛卡尔积(即两个表中所有记录的所有可能组合)中生成DELETED
条记录,这些记录将插入{{1} }。
那是你想做的吗?
最有可能的是,您希望加入tbl1
上的表格:
PRIMARY KEY
这会将INSERT
INTO tbl1
SELECT @createDate,
@operationType,
@status,
@updatedColumnsMask,
d.F1,
i.F1,
d.F2,
i.F2,
d.F3,
i.F3,
d.F4,
i.F4,
d.F5,
i.F5,
...
FROM INSERTED i
FULL JOIN
DELETED d
ON i.id = d.id
的更新视为删除记录并使用新的PK
插入另一条记录。
答案 1 :(得分:0)
感谢Quassnoi,“全加入”是一个好主意。这对我很有帮助。
此外,我尝试更新部分表(一次1000个项目)以使我的代码更快地运行,因为对于某些公司我需要更新超过160 000行。
而不是旧代码:
UPDATE tblSomeTable set someVal = @someVal where companyId = @companyId
我用下面的一个:
declare @rc integer = 0
declare @parts integer = 0
declare @index integer = 0
declare @portionSize int = 1000
-- select Ids for update
declare @tempIds table (id int)
insert into @tempIds
select id from tblSomeTable where companyId = @companyId
-- calculate amount of iterations
set @rc=@@rowcount
set @parts = @rc / @portionSize + 1
-- update table in portions
WHILE (@parts > @index)
begin
UPDATE TOP (@portionSize) t
SET someVal = @someVal
FROM tblSomeTable t
JOIN @tempIds t1 on t1.id = t.id
WHERE companyId = @companyId
delete top (@portionSize) from @tempIds
set @index += 1
end
您如何看待这个?是否有意义?如果是,如何选择正确的份量?
还是简单的更新还有很好的解决方案?我只是想在将来避免锁定。
由于