اسکریپتی برای مانیتور کوئریهای پرهزینه ( Disk, Cpu ,IO ,… ) در SqlServer
هدف این اسکریپت، پایش و گزارشگیری دقیق از اجرای دستورات SQL در یک بازه زمانی مشخص است تا به شناسایی نقاط ضعف و بهینهسازی عملکرد پایگاه داده کمک کند. این اسکریپت اطلاعات حیاتی مانند تعداد دفعات اجرای کوئریها، زمان مصرفی پردازش CPU، حجم عملیات ورودی/خروجی (I/O) و مدتزمان سپریشده برای اجرای هر کوئری را جمعآوری میکند. با این اطلاعات، یک نمای کلی از عملکرد کوئریها و تأثیر آنها بر منابع سیستم به دست میآید.
این ابزار بهویژه در تشخیص مشکلات عملکردی مفید است و به شما کمک میکند تا کوئریهایی را که باعث کاهش سرعت یا ایجاد بار اضافی بر روی پایگاه داده میشوند، شناسایی کنید.
-- ************************************************************************************************* GO DECLARE @Database sysname = 'MyDb', -- Set the database name @MonitorPeriod varchar(10) = '01:00:00' -- 1 hour -- set this to the time period you want to monitor for BEGIN SET NOCOUNT ON; SET ARITHABORT OFF; SET ANSI_WARNINGS OFF; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; DROP TABLE IF EXISTS #CombinedResults; CREATE TABLE #CombinedResults ( DBName sysname, QueryText varchar(MAX), Execution_count bigint, total_cpu_time bigint, total_IO bigint, total_physical_reads bigint, total_logical_reads bigint, total_logical_writes bigint, total_elapsed_time bigint, Identifier tinyint ,plan_handle varbinary(64) not null ,last_execution_time datetime ); DECLARE @Iteration tinyint = 1; WHILE @Iteration <= 2 BEGIN ;WITH PlanStats AS ( SELECT st.dbid, st.text AS QueryText, cp.plan_handle, MAX(cp.usecounts) AS Execution_count, SUM(qs.total_worker_time) AS total_cpu_time, SUM(qs.total_physical_reads + qs.total_logical_reads + qs.total_logical_writes) AS total_IO, SUM(qs.total_physical_reads) AS total_physical_reads, SUM(qs.total_logical_reads) AS total_logical_reads, SUM(qs.total_logical_writes) AS total_logical_writes, SUM(qs.total_elapsed_time) AS total_elapsed_time, MAX(qs.last_execution_time) AS last_execution_time FROM sys.dm_exec_cached_plans cp INNER JOIN sys.dm_exec_query_stats qs ON cp.plan_handle = qs.plan_handle CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st WHERE DB_NAME(st.dbid) IS NOT NULL AND DB_NAME(st.dbid) LIKE @Database GROUP BY st.dbid, st.text, cp.plan_handle ) INSERT INTO #CombinedResults SELECT DB_NAME(ps.dbid) AS DBName, ps.QueryText, SUM(ps.Execution_count) AS Execution_count, SUM(ps.total_cpu_time) AS total_cpu_time, SUM(ps.total_IO) AS total_IO, SUM(ps.total_physical_reads) AS total_physical_reads, SUM(ps.total_logical_reads) AS total_logical_reads, SUM(ps.total_logical_writes) AS total_logical_writes, SUM(ps.total_elapsed_time) AS total_elapsed_time, @Iteration AS Identifier ,ps.plan_handle ,max(ps.last_execution_time) FROM PlanStats ps GROUP BY ps.dbid, ps.QueryText, plan_handle; -- Wait for the specified monitoring period during the first iteration IF @Iteration = 1 BEGIN WAITFOR DELAY @MonitorPeriod; END SET @Iteration = @Iteration + 1; END -- ************************************************************************************************ -- Results -- ************************************************************************************************ SELECT ISNULL(A.DBName, B.DBName) AS DBName, ISNULL(A.QueryText, B.QueryText) AS QueryText, ISNULL(A.Execution_count, 0) - ISNULL(B.Execution_count, 0) AS Execution_count, ISNULL(A.total_cpu_time, 0) - ISNULL(B.total_cpu_time, 0) AS total_cpu_time, (ISNULL(A.total_cpu_time,0) - ISNULL(B.total_cpu_time, 0)) / NULLIF(ISNULL(A.Execution_count,0) - ISNULL(B.Execution_count, 0), 0) AS avg_cpu_time, ISNULL(A.total_IO, 0) - ISNULL(B.total_IO, 0) AS total_IO, (ISNULL(A.total_IO,0) - ISNULL(B.total_IO, 0)) / NULLIF(ISNULL(A.execution_count,0) - ISNULL(B.execution_count, 0), 0) AS avg_total_IO, ISNULL(A.total_physical_reads, 0) - ISNULL(B.total_physical_reads, 0) AS total_physical_reads, (ISNULL(A.total_physical_reads,0) - ISNULL(B.total_physical_reads, 0)) / NULLIF(ISNULL(A.execution_count,0) - ISNULL(B.execution_count, 0), 0) AS avg_physical_read, ISNULL(A.total_logical_reads, 0) - ISNULL(B.total_logical_reads, 0) AS total_logical_reads, (ISNULL(A.total_logical_reads, 0) - ISNULL(B.total_logical_reads, 0)) / NULLIF(ISNULL(A.execution_count,0) - ISNULL(B.execution_count, 0), 0) AS avg_logical_read, ISNULL(A.total_logical_writes, 0) - ISNULL(B.total_logical_writes, 0) AS total_logical_writes, (ISNULL(A.total_logical_writes, 0) - ISNULL(B.total_logical_writes, 0)) / NULLIF(ISNULL(A.execution_count,0) - ISNULL(B.execution_count, 0), 0) AS avg_logical_writes, ISNULL(A.total_elapsed_time, 0) - ISNULL(B.total_elapsed_time, 0) AS total_elapsed_time, (ISNULL(A.total_elapsed_time, 0) - ISNULL(B.total_elapsed_time, 0)) / NULLIF(ISNULL(A.execution_count, 0) - ISNULL(B.execution_count, 0), 0) AS avg_elapsed_time, ISNULL(A.last_execution_time, A.last_execution_time) last_execution_time FROM (SELECT * FROM #CombinedResults WHERE Identifier = 2) A LEFT JOIN (SELECT * FROM #CombinedResults WHERE Identifier = 1) B ON A.DBName = B.DBName AND A.QueryText = B.QueryText AND A.plan_handle = B.plan_handle WHERE ISNULL(A.Execution_count, 0) - ISNULL(B.Execution_count, 0) <> 0 ORDER BY 4 DESC; DROP TABLE #CombinedResults; END GO