SQL 服务器游标,糟糕的性能?

SQL Server cursors, horrid performance?

一位半技术客户报告他们的 SQL 基于服务器的应用程序(第 3 方)定期崩溃。他们无法确定是哪组输入导致了这种情况,但似乎是在特定 "project code".

上调用特定 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 会崩溃。几个 运行s,没有改善。

所以我使用 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 查询,每个查询都经过管道并返回,最终 运行 准确 相同的查询。那么,可能 100 倍 比运行使用服务器本身的本地语言编写的代码快多少?弄得我脑袋疼。

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

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

我会 运行 从 SQL Server Studio 登录到单独的 table 在每个 EXECUTE sp_executesql @SQL 之前和之后以及崩溃之后分析这个特定过程输出。

也可能是 SQL Server Studio 在尝试加载所有这些结果集时内存不足。

这有点偏离 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/