Полутехнический клиент сообщил, что их приложение на основе SQLServer (сторонняя сторона) периодически разбилось. Они не смогли определить, какой набор входных данных вызвал это, но, похоже, это происходит, когда конкретный SP был вызван на конкретный «код проекта».Курсоры SQL Server, ужасная производительность?
Так что я написал 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 минут, студия обрушится. Несколько прогонов, никаких улучшений.
Так что я переписал код в VBA в Excel с помощью ADO:
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 действительно , что slow? Я имею в виду, что версия VBA должна запускать три отдельных запроса ADO для каждой итерации, каждый из которых проходит по каналу и обратно, и в конечном итоге выполняет точный запрос . Итак, как может это возможно быть 100 раз быстрее, чем запустить код на самом сервере на своем родном языке? Это заставляет мой мозг болеть.
Или я вижу проблему в самой студии? Я подумал, что, возможно, у него заканчивается память, но, наблюдая за ее запуском, я не вижу, чтобы она работала быстрее, чем раньше. Но возможность все еще существует ... может кто-то предложить способ проверить это?
Сколько строк есть для курсора для обработки? Кроме того, вы не должны использовать курсор с настройками по умолчанию, локальные, read_only и forward_only должны всегда использоваться, если это возможно. –
Хороший вопрос. Проверка ... 188 SP, 45 проектов. –
Это звучит не так. Являются ли процедуры, возвращающие наборы результатов? Возможно, использование результата для текста вместо сетки поможет. –