SQL Server游标性能缓慢

Sta*_*Csh 4 sql-server sql-server-2008-r2

我开始在sql server 2008中第一次使用存储过程中的游标.我已经做了一些初步阅读,我知道它们有很大的性能限制.在我目前的情况下,我认为它们是必要的(我想在符号表中为每个股票代码运行多个存储过程.

编辑:我将在每个符号上调用的sprocs大部分是插入操作来计算符号相关值,例如5天移动平均值,平均每日交易量,ATR(平均真实范围).这些值中的大部分将根据每日定价和数量表中的数据进行计算...我想简化对冗余检索的数据值的检索,否则...例如,我想得到每个值将每日定价和卷数据符号转换为表变量...然后将临时表传递给调用我刚刚提到的每个聚合函数的存储过程.希望有道理......

所以我的初始"外循环"基于光标的存储过程在下面..它在几分钟后超时,而没有返回到输出窗口.

ALTER PROCEDURE dbo.sprocSymbolDependentAggsDriver2

    AS

    DECLARE @symbol nchar(10)
    DECLARE symbolCursor CURSOR
    STATIC FOR
    SELECT Symbol FROM tblSymbolsMain ORDER BY Symbol

    OPEN symbolCursor
    FETCH NEXT FROM symbolCursor INTO @symbol
    WHILE @@FETCH_STATUS = 0
        SET @symbol = @symbol + ': Test.'
        FETCH NEXT FROM symbolCursor INTO @symbol

    CLOSE symbolCursor
    DEALLOCATE symbolCursor
Run Code Online (Sandbox Code Playgroud)

当我在没有@symbol局部变量的情况下运行它并在while循环中消除它的赋值时,它似乎运行正常.在该任务中是否明显违反了绩效最佳做法?谢谢..

wom*_*omp 5

"在我目前的情况下,我认为它们是必要的(我想在符号表中为每个股票代码运行多个存储过程."

游标很少是必需的.

从上面的例子中,我认为一个简单的WHILE循环很容易取代你的光标.改编自SQL游标 - 如何避免它们(我最喜欢的SQL书签之一)

-- Create a temporary table...
CREATE TABLE #Symbols (
 RowID int IDENTITY(1, 1), 
 Symbol(nvarchar(max))
)
DECLARE @NumberRecords int, @RowCount int
DECLARE @Symbol nvarchar(max)

-- Get your data that you want to loop over
INSERT INTO #Symbols (Symbol)
SELECT Symbol
FROM tblSymbolsMain 
ORDER BY Symbol

-- Get the number of records you just grabbed
SET @NumberRecords = @@ROWCOUNT
SET @RowCount = 1


-- Just do a WHILE loop.  No cursor necessary.
WHILE @RowCount <= @NumberRecords
BEGIN
 SELECT @Symbol = Symbol
 FROM #Symbols
 WHERE RowID = @RowCount

 EXEC <myProc1> @Symbol
 EXEC <myProc2> @Symbol
 EXEC <myProc3> @Symbol

 SET @RowCount = @RowCount + 1
END


DROP TABLE #Symbols
Run Code Online (Sandbox Code Playgroud)

  • 为什么你认为 while 循环不是游标?或者说它会表现得更好?我已经写了一些关于此的博客。https://sqlblog.org/blogs/aaron_bertrand/archive/2012/01/26/the-fallacy-that-a-while-loop-isn-ta-cursor.aspx (2认同)

Aar*_*and 3

您实际上并不需要所有显式的光标爵士乐来构建字符串。这可能是一种更有效的方法:

DECLARE @symbol NVARCHAR(MAX) = N'';

SELECT @symbol += ': Test.'
    FROM dbo.tblSymbolsMain 
    ORDER BY Symbol;
Run Code Online (Sandbox Code Playgroud)

尽管我怀疑您实际上想查看符号的名称,例如

DECLARE @symbol NVARCHAR(MAX) = N'';

SELECT @symbol += N':' + Symbol
    FROM dbo.tblSymbolsMain 
    ORDER BY Symbol;
Run Code Online (Sandbox Code Playgroud)

需要注意的是,虽然您通常会遵守要遵守的顺序,但这并不能保证。所以如果你想坚持光标,至少要按如下方式声明光标:

DECLARE symbolCursor CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
...
Run Code Online (Sandbox Code Playgroud)

另外,在我看来, NCHAR(10) 不足以保存您尝试填充到其中的数据,除非您只有一行(这就是我在NVARCHAR(MAX)上面选择的原因)。

我同意 Abe 的观点......您很可能不需要为游标中的每一行触发存储过程,但要提出解决方法(这几乎肯定会更有效),我们必须了解这些存储过程的实际用途。