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/
一位半技术客户报告他们的 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/