Я работаю над проблемой производительности хранимых процедур уже более недели и связана с другим моим постом о Stackoverflow здесь . Позвольте мне дать вам некоторую справочную информацию.
У нас есть ночной процесс, который запускается и запускается хранимой процедурой, которая вызывает много-много других хранимых процедур. Множество вызываемых хранимых процедур вызывают другие и т. Д. Я рассмотрел некоторые из вызываемых процедур, и в них есть всякие пугающие сложные вещи, такие как обработка строк XML, ненужное чрезмерное использование курсоров, чрезмерное использование подсказок NOLOCK, редкое использование обработки на основе множеств и т. д. - список можно продолжать, это ужасно.
Этот ночной процесс в нашей производственной среде занимает в среднем 1:15. Иногда для запуска требуется 2 часа, что недопустимо. Я создал тестовую среду на оборудовании, идентичном производственному, и запустил процесс. Это заняло 45 минут, когда я впервые запустил его. Если я восстанавливаю базу данных в ту же точку и запускаю ее снова, это займет больше времени: на самом деле, если я повторю это действие несколько раз (восстановление и повторный запуск), процесс будет прогрессивно дольше, пока он не достигнет примерно 2 часов. Это действительно озадачивает меня, потому что я каждый раз восстанавливаю базу данных до одной и той же точки. На сервере нет других пользовательских баз данных.
Я подумал о двух направлениях расследования:
- Планы запросов и подмена параметров
- Tempdb
В качестве теста я перезапустил SQL Server, чтобы очистить кеш и базу данных tempdb, и повторно запустил процесс с тем же восстановлением базы данных. Процесс занял 45 минут. Я повторил это несколько раз, чтобы убедиться, что это повторяется - снова это заняло 45 минут каждый раз. Затем я предпринял несколько тестов, чтобы попытаться изолировать удивительное увеличение времени выполнения, когда SQL Server не перезапускается:
- Запустить начальную хранимую процедуру с RECOMPILE
- Перед запуском процедуры выполните executre DBCC FREEPROCCACHE, чтобы очистить кеш процедуры
- Перед запуском процедуры выполните CHECKPOINT, а затем DBCC DROPCLEANBUFFERS, чтобы убедиться, что кэш был пустым и чистым
Выполнен следующий скрипт, чтобы гарантировать, что все хранимые процедуры были помечены для перекомпиляции:
DECLARE @proc_schema SYSNAME
DECLARE @proc_name SYSNAME
DECLARE prcCsr CURSOR local
FOR SELECT specific_schema,
specific_name
FROM INFORMATION_SCHEMA.routines
WHERE routine_type = 'PROCEDURE'
OPEN prcCsr
FETCH NEXT FROM prcCsr INTO @proc_schema, @proc_name
DECLARE @stmt NVARCHAR(MAX)
WHILE @@FETCH_STATUS = 0
BEGIN
SET @stmt = N'exec sp_recompile ''[' + @proc_schema + '].['
+ @proc_name + ']'''
-- PRINT @stmt -- DEBUG
EXEC ( @stmt
)
FETCH NEXT FROM prcCsr INTO @proc_schema, @proc_name
END
Во всех вышеперечисленных тестах процедура выполняется дольше и дольше с тем же восстановлением базы данных. Я действительно в растерянности сейчас относительно того, что попробовать. Изучение кода на данный момент является одним из вариантов, но на самом деле на его оптимизацию уйдет 3-6 месяцев, поскольку есть много возможностей для улучшения. В чем я действительно заинтересован, так это в том, почему время выполнения процедуры увеличивается каждый раз, когда выполняется восстановление базы данных, даже когда очищены процедуры и буферные кэши?
Я также исследовал базу данных tempdb и попытался очистить там старые таблицы, как описано в моем другом посте stackoverflow, но я не могу вручную очистить временные таблицы, которые были созданы из переменных таблицы, и похоже, что они хочу исчезнуть самостоятельно (даже после того, как покинул их на 24 часа).
Будем весьма благодарны за любые идеи или предложения по дальнейшему тестированию. Я использую 64-разрядную версию Enterprise Edition SQL Server 2005 с пакетом обновления 3 (SP3) на Windows 2003 R2 Ent. редакция кластера.
С уважением,
Mark.