快速批量更新

时间:2014-01-15 17:07:43

标签: sql sql-server performance sql-update

我需要更新整个表格。我需要一个给定的行(在这种情况下为501)来处理表中的所有行(包括它自己)。

这是我到目前为止所做的,但需要8秒(160万行):

DECLARE @ID INT = 501;
DECLARE @Lambda DECIMAL(10, 5) = 0.5;
set statistics time on

UPDATE RectangleOne
SET RectangleOne.Jaccard = ((1 - @Lambda) * RectangleOne.Jaccard) + @Lambda *dbo.fn_ComputeJaccard(
        RectangleTwo.MinX, RectangleTwo.MinY, RectangleTwo.MaxX, RectangleTwo.MaxY,
        RectangleOne.MinX, RectangleOne.MinY, RectangleOne.MaxX, RectangleOne.MaxY)
FROM PreProcessed RectangleOne
INNER JOIN PreProcessed RectangleTwo
ON RectangleTwo.ID = @ID

set statistics time off

我希望有人能看到一个明显的瓶颈?如果没有,我应该考虑什么才能尝试提高性能?

我应该补充说,执行计算只需要290毫秒(测试时):

DECLARE @ID INT = 501;
DECLARE @Lambda DECIMAL(10, 5) = 0.5;
set statistics time on
    SELECT COUNT(1)
    FROM PreProcessed RectangleOne
    INNER JOIN PreProcessed RectangleTwo
    ON RectangleTwo.ID = @ID
    WHERE ((1 - @Lambda) * RectangleOne.Jaccard) + @Lambda *dbo.fn_ComputeJaccard(
            RectangleTwo.MinX, RectangleTwo.MinY, RectangleTwo.MaxX, RectangleTwo.MaxY,
            RectangleOne.MinX, RectangleOne.MinY, RectangleOne.MaxX, RectangleOne.MaxY) > -1
set statistics time off

执行基本更新只需要1500毫秒(使用测试):

UPDATE PreProcessed
SET PreProcessed.Jaccard = PreProcessed.Jaccard*@Lambda;

所以我不清楚为什么我的实际查询会花费多长时间......

1 个答案:

答案 0 :(得分:1)

因此,正如上面的评论中所讨论的,节省大量时间的一种方法是使用变量来使INNER JOIN不必要。

另外......可能很小......我创建了一个新变量@Lambda_Flip,所以1 - @Lambda的计算只进行一次......然后使用@Lambda_Flip,在UPDATE的那个地方。

最后,化妆品的变化:我在(@Lambda * dbo.fn_ComputeJaccard(@R2MinX, @R2MinY, @R2MaxX, @R2MaxY,RectangleOne.MinX, RectangleOne.MinY, RectangleOne.MaxX, RectangleOne.MaxY))附近添加了一对括号。即使你和我知道在添加之前它已经被执行了,由于SQL的操作顺序......我认为这些括号可能使读者更容易理解,从左到右阅读。

DECLARE @ID INT = 501;
DECLARE @Lambda DECIMAL(10, 5) = 0.5;
DECLARE @Lambda_Flip DECIMAL(10, 5) = 1 - @Lambda;
DECLARE @R2MinX INT, @R2MinY INT, @R2MaxX INT, @R2MaxY INT;
set statistics time on

SELECT @R2MinX = MinX, @R2MinY = MinY, @R2MaxX = MaxX, @R2MaxY = MaxY
FROM PreProcessed 
WHERE ID = @ID;

UPDATE RectangleOne
SET RectangleOne.Jaccard = (@Lambda_Flip * RectangleOne.Jaccard) 
+ (@Lambda * dbo.fn_ComputeJaccard(
        @R2MinX, @R2MinY, @R2MaxX, @R2MaxY,
        RectangleOne.MinX, RectangleOne.MinY, RectangleOne.MaxX, RectangleOne.MaxY))
FROM PreProcessed RectangleOne

set statistics time off

如果你使用它或它的变体,那么(一如既往)请让我们和后人知道什么有效,以及表现如何改变:) ...谢谢!