SQL Server游标,可怕的性能?

时间:2016-05-03 14:56:49

标签: sql-server tsql cursor

一位半技术客户报告他们的基于SQLServer的应用程序(第三方)定期崩溃。他们无法确定导致这种情况的输入集,但是当特定的SP被调用特定的项目代码时,它似乎正在发生。

所以我编写了一个T-SQL脚本,用每个可能的输入运行每个SP并在SQL Server Studio中运行它:

--doing this makes it easier to see error messages
SET NOCOUNT ON

DECLARE @sp_name NVARCHAR(50) -- proc name
DECLARE @id_proj NVARCHAR(50) -- project name
DECLARE @SQL NVARCHAR(250) -- SQL command-

DECLARE sp_cursor CURSOR FOR SELECT SPECIFIC_NAME FROM information_schema.routines WHERE routine_type = 'PROCEDURE'

OPEN sp_cursor
FETCH NEXT FROM sp_cursor INTO @sp_name
WHILE @@FETCH_STATUS = 0
BEGIN
 DECLARE pr_cursor CURSOR FOR SELECT ProjName FROM dtaprojects
 OPEN pr_cursor
 FETCH NEXT FROM pr_cursor INTO @id_proj
    WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @SQL = 'EXEC ' + @sp_name + ' ''' + @id_proj + ''''
        BEGIN TRY
            EXECUTE sp_executesql @SQL
        END TRY
        BEGIN CATCH
            PRINT 'Error when running SP ''' + @sp_name + ''' with project ''' + @id_proj + ''''
        END CATCH
        FETCH NEXT FROM pr_cursor INTO @id_proj
    END
    CLOSE pr_cursor
    DEALLOCATE pr_cursor
    FETCH NEXT FROM sp_cursor INTO @sp_name
END;
CLOSE sp_cursor
DEALLOCATE sp_cursor

--and just to be safe...
SET NOCOUNT OFF

跑了大约7分钟后,Studio会崩溃。几次运行,没有任何改进。

所以我使用ADO在Excel中用VBA重新编写代码:

Public Sub TestStoredProcs()
    Dim WS As Worksheet
    Set WS = ThisWorkbook.Sheets(1)
    Dim R As Long
    R = 1

    Dim SQL As String

    Dim DS As New Recordset 
    Dim DP As New Recordset 
    Dim DR As New Recordset

    Dim Cnn As New Connection
    Cnn.ConnectionString = cConStr
    Cnn.Open

    DS.Open "SELECT SPECIFIC_NAME FROM information_schema.routines WHERE routine_type='PROCEDURE'", Cnn
    Do Until DS.EOF
        DP.Open "SELECT ProjName FROM dtaprojects", Cnn
        Do Until DP.EOF
            SQL = "N'EXEC " & Trim(DS!SPECIFIC_NAME) & " ''" & Trim(DP!projname) & "'''"
            WS.Cells(R, 1) = DS!SPECIFIC_NAME
            WS.Cells(R, 2) = DP!projname

            Debug.Print "EXECUTE sp_executesql " & SQL

            DR.Open "EXECUTE sp_executesql " & SQL, Cnn
            WS.Cells(R, 3) = DR.RecordCount
            DR.Close

            R = R + 1
            DP.MoveNext
        Loop
        DP.Close
        DS.MoveNext
    Loop
    DS.Close
End Sub

这在26秒内完成。

好的,那么这里发生了什么? T-SQL游标真的 慢吗?我的意思是,VBA版本必须为每次迭代运行三个单独的ADO查询,每个查询遍历管道并返回,最终运行 exact 相同的查询。那么,可能 它让我的大脑受伤了。

或者我在Studio中看到了问题?我想也许它的内存不足,但看着它运行我看不到它在开始时比结束更快。但是可能性仍然存在......有人可以建议一种方法来测试吗?

2 个答案:

答案 0 :(得分:2)

当您运行SQL Server Studio中的所有过程时,它会加载并尝试显示所有结果集。 Excel中的ADO没有。这解释了时间上的差异:SQL Server Studio检索存储过程返回的所有行。

我会在每个EXECUTE sp_executesql @SQL之前和之后从SQL Server Studio登录到单独的表中运行相同的操作,并在崩溃后分析此特定过程输出。

也可能是SQL Server Studio在尝试加载所有这些结果集时崩溃了。

答案 1 :(得分:0)

这是ADO的一个主题,但绝对是关于性能的话题。如果要处理非常大的数据集,请确保对表进行索引。你可能已经知道了这一点,但只是为了确保......

https://www.simple-talk.com/sql/learn-sql-server/sql-server-index-basics/

https://www.simple-talk.com/sql/database-administration/brads-sure-guide-to-indexes/