SQL:查询超时已过期

时间:2011-03-29 11:22:16

标签: sql sql-server

我有一个简单的查询更新表(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

如果我执行更新查询,我会超时。

如何优化逻辑以避免超时?

谢谢。

2 个答案:

答案 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 = 6250000INSERTED的笛卡尔积(即两个表中所有记录的所有可能组合)中生成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

您如何看待这个?是否有意义?如果是,如何选择正确的份量?

还是简单的更新还有很好的解决方案?我只是想在将来避免锁定。

由于