Вашему вниманию предлагается макет сценария и методики, позволяющей организовать учёт исполнения хранимых процедур пользовательской базы данных. Пример сценария само-достаточен, т.е. для его успешной работы необходимо только заменить в тексте сценария слово 'ТУТ ДОЛЖНО БЫТЬ ИМЯ ВАШЕЙ БАЗЫ ДАННЫХ!!!!!!!!!!!!!!!!' на имя вашей базы данных, использование процедур которой необходимо отслеживать. Сценарий создаёт задание Агента SQL Server, которое по установленному расписанию (расписание подбирается в зависимости от нагрузки сервера) исполняет сценарий T-SQL. Исполняемый заданием сценарий создаёт по необходимости в базе TEMPDB таблицу Activproc, и потом записывает в ней статистику использования процедур, получая актуальные на момент исполнения метаданные сервера. Для того, чтобы понять принципы работы сценария, ознакомьтесь с теми разделами BOL, в которых описаны задействованные в сценарии административные динамические представления и функции.
Предлагаемая методика отслеживания активности процедур не гарантирует 100% точности собираемой статистики. Она полагается на то, что метаданные об исполнении процедур будут достаточно долго доступны и попадут в таблицу. Для сильно нагруженных серверов этого может не произойти. Однако, преимуществом этой методики является тот факт, что она не так нагружает сервер, как трассировка.
В примере сценария местом размещения таблицы статистики процедур выбрана база данных TEMPDB. Этот факт нужно учитывать, поскольку при каждом запуски службы SQL Server эта база данных создаётся заново, и информация в таблице статистики будет утеряна.
Пример сценария:
USE [msdb]
GO
DECLARE @jobId BINARY(16)
EXEC msdb.dbo.sp_add_job @job_name=N'Activproc',
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=2,
@notify_level_netsend=0,
@notify_level_page=0,
@delete_level=0,
@description=N'Собирает простую статистику по использованию хранимых процедур',
@category_name=N'Database Maintenance',
@owner_login_name=N'sa',
-- @notify_email_operator_name=N'MS-SQL-Admins',
@job_id = @jobId OUTPUT
EXEC msdb.dbo.sp_add_jobstep @job_id=@jobId,
@step_name=N'Activproc 1',
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_success_step_id=0,
@on_fail_action=2,
@on_fail_step_id=0,
@retry_attempts=0,
@retry_interval=0,
@os_run_priority=0,
@subsystem=N'TSQL',
@command=N'IF NOT EXISTS (SELECT * FROM tempdb.sys.objects WHERE name = ''Activproc'')
CREATE TABLE tempdb.[dbo].[Activproc]
(
[SP_Name] sysname NOT NULL,
[last_execution_time] datetime NOT NULL,
[avg_elapsed_time_sec] money NOT NULL
)
DECLARE @SP_Name sysname, @last_execution_time datetime, @avg_elapsed_time_sec money
DECLARE c_Activproc CURSOR GLOBAL FAST_FORWARD READ_ONLY FOR
SELECT TOP 100 PERCENT OBJECT_NAME(s.objectid,s.dbid) AS SP_Name
, MAX(st.last_execution_time) AS last_execution_time
, SUM(CAST((st.total_elapsed_time * 1.0 /100000)/st.execution_count AS money))
AS avg_elapsed_time_sec
FROM master.sys.dm_exec_cached_plans AS c
CROSS APPLY master.sys.dm_exec_query_plan (c.plan_handle) AS q
INNER JOIN master.sys.dm_exec_query_stats AS st
ON c.plan_handle = st.plan_handle
CROSS APPLY master.sys.dm_exec_sql_text(sql_handle) AS s
WHERE c.cacheobjtype = ''Compiled Plan''
AND c.objtype = ''Proc''
AND q.dbid = DB_ID()
GROUP BY DB_NAME(q.dbid),OBJECT_NAME(s.objectid,s.dbid)
ORDER BY avg_elapsed_time_sec DESC
OPEN GLOBAL c_Activproc
WHILE 1 = 1
BEGIN
FETCH c_Activproc INTO @SP_Name, @last_execution_time, @avg_elapsed_time_sec
IF @@fetch_status <> 0 BREAK
IF @SP_Name NOT IN (SELECT SP_Name FROM tempdb.dbo.Activproc WHERE SP_Name = @SP_Name)
BEGIN
INSERT INTO tempdb.dbo.Activproc (SP_Name, last_execution_time, avg_elapsed_time_sec)
VALUES (@SP_Name, @last_execution_time, @avg_elapsed_time_sec)
END
ELSE
BEGIN
UPDATE tempdb.dbo.Activproc
SET last_execution_time = @last_execution_time, avg_elapsed_time_sec = @avg_elapsed_time_sec
WHERE SP_Name = @SP_Name
END
END
CLOSE GLOBAL c_Activproc
DEALLOCATE c_Activproc
GO',
@database_name=N'ТУТДОЛЖНОБЫТЬИМЯВАШЕЙБАЗЫДАННЫХ!!!!!!!!!!!!!!!!',
@flags=4
EXEC msdb.dbo.sp_update_job @job_id=@jobId,
@start_step_id = 1
EXEC msdb.dbo.sp_add_jobschedule @job_id=@jobId,
@name=N'1',
@enabled=1,
@freq_type=4,
@freq_interval=1,
@freq_subday_type=4,
@freq_subday_interval=1,
@freq_relative_interval=0,
@freq_recurrence_factor=0,
@active_start_date=20090217,
@active_end_date=99991231,
@active_start_time=0,
@active_end_time=235959,
-- @schedule_uid=N'ffb0a0d2-93bc-49d0-9fc7-4e35140bfd9f'
EXEC msdb.dbo.sp_add_jobserver @job_id=@jobId,
@server_name = N'(local)'
GO
Следующий сценарий позволяет запросить статистику использования хранимых процедур:
SELECT [SP_Name]
,[last_execution_time]
,[avg_elapsed_time_sec]
FROM [tempdb].[dbo].[Activproc]
ORDER BY [avg_elapsed_time_sec] DESC
GO