对于性能 - 应该使用Loop或Row_Number来更新数据集吗?

时间:2014-07-01 18:54:19

标签: sql-server

有人可以解释一下使用RowCounter的While循环是否比在SQL服务器中使用ROW_NUMBER更快或更慢?

或者没有区别?

现有的存储过程太复杂了,无法将其全部放在View中并且速度非常慢..这是While循环,但是如何在Sql Server 2008 R2中使用ROW_NUMBER来完成,并且会有任何性能优势?

DECLARE @StopRow AS INT

SELECT @StopRow = MAX(RowID)
FROM #Temp1

DECLARE @RowCounter AS INT

SET @RowCounter = 1

DECLARE @colID INT

WHILE (@RowCounter <= @StopRow)
BEGIN
    SELECT @colID = colID
    FROM #Temp1
    WHERE colRowID = @RowCounter

    IF (
            EXISTS (
                SELECT ParentColID
                FROM ParentTable a WITH (NOLOCK)
                JOIN MoreTableData b WITH (NOLOCK) ON a.priID = b.priID
                    AND colID = @colID
                WHERE anotherID NOT IN (
                        SELECT anotherID
                        FROM @anotherTempTable
                        )
                )
            )
        UPDATE #Temp1
        SET aFlag = 0
        WHERE colRowID = @RowCounter

    SET @RowCounter = @RowCounter + 1
END

现在发现这个StackOverflow,我理解基于SET(UPDATE)的verbage .. How to convert a loop in SQL to Set-based logic

2 个答案:

答案 0 :(得分:2)

为什么你需要任何循环?可以在一个UPDATE吗?

   UPDATE T
        SET aFlag = 0       
   FROM #Temp1 AS T       
   WHERE EXISTS (
                SELECT ParentColID
                FROM ParentTable a WITH (NOLOCK)
                JOIN MoreTableData b WITH (NOLOCK) 
                    ON a.priID = b.priID
                    AND a.colID = t.colID
                WHERE anotherID NOT IN (
                        SELECT anotherID
                        FROM @anotherTempTable
                        )
                )

未经测试。

答案 1 :(得分:1)

通常,基于集合的解决方案比基于游标的解决方案提供更好的性能。

如果考虑性能,我会尝试使用基于集合的解决方案重写我的解决方案:

UPDATE  t1
SET     aFlag = 0
FROM    #Temp1 t1
WHERE   colRowID BETWEEN 1 AND (SELECT MAX(RowID) FROM #Temp1)
AND     EXISTS 
(
    SELECT ParentColID
        FROM ParentTable a 
        JOIN MoreTableData b ON a.priID = b.priID
        AND colID = t1.colID
        WHERE anotherID NOT IN 
        (
            SELECT anotherID
            FROM   @anotherTempTable
        )
)

然后,在开发/服务器服务器上,我将使用SQL跟踪/扩展事件会话来跟踪以下主要KPI:持续时间,CPU,[逻辑]读取,我将比较这两个解决方案(基于光标与基于集合)

注意#1:(SELECT MAX(RowID) FROM #Temp1)子查询应该只进行一次评估,因为它不是相关的子查询。

注意#2:尝试用NOT EXISTS替换NOT IN。 Reason