Вашему вниманию предлагается макет сценария и методики, позволяющей организовать учёт исполнения хранимых процедур пользовательской базы данных. Пример сценария само-достаточен, т.е. для его успешной работы необходимо только заменить в тексте сценария слово‘ТУТДОЛЖНОБЫТЬИМЯВАШЕЙБАЗЫДАННЫХ!!!!!!!!!!!!!!!!’ на имя вашей базы данных, использование процедур которой необходимо отслеживать. Сценарий создаёт задание Агента 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

