SQL Server 诊断查询-(3)

Query #27 Database Properties

   -- Recovery model, log reuse wait description, log file size, log usage size

   -- and compatibility level for all databases on instance

SELECT db.[name] AS [Database Name], db.recovery_model_desc AS [Recovery Model], db.state_desc, db.containment_desc,

   db.log_reuse_wait_desc AS [Log Reuse Wait Description], 

   CONVERT(DECIMAL(18,2), ls.cntr_value/1024.0) AS [Log Size (MB)], CONVERT(DECIMAL(18,2), lu.cntr_value/1024.0) AS [Log Used (MB)],

   CAST(CAST(lu.cntr_value AS FLOAT) / CAST(ls.cntr_value AS FLOAT)AS DECIMAL(18,2)) * 100 AS [Log Used %], 

   db.[compatibility_level] AS [DB Compatibility Level], db.page_verify_option_desc AS [Page Verify Option], 

   db.is_auto_create_stats_on, db.is_auto_update_stats_on, db.is_auto_update_stats_async_on, db.is_parameterization_forced, 

   db.snapshot_isolation_state_desc, db.is_read_committed_snapshot_on, db.is_auto_close_on, db.is_auto_shrink_on, 

   db.target_recovery_time_in_seconds, db.is_cdc_enabled, db.is_published, db.is_distributor, db.is_encrypted,

   db.group_database_id, db.replica_id,db.is_memory_optimized_elevate_to_snapshot_on, 

   db.delayed_durability_desc, db.is_auto_create_stats_incremental_on,

   db.is_query_store_on, db.is_sync_with_backup, 

   db.is_supplemental_logging_enabled, db.is_remote_data_archive_enabled      

   FROM sys.databases AS db WITH (NOLOCK)

   INNER JOIN sys.dm_os_performance_counters AS lu WITH (NOLOCK)

   ON db.name = lu.instance_name

   INNER JOIN sys.dm_os_performance_counters AS ls WITH (NOLOCK)

   ON db.name = ls.instance_name

   WHERE lu.counter_name LIKE N'Log File(s) Used Size (KB)%' 

   AND ls.counter_name LIKE N'Log File(s) Size (KB)%'

   AND ls.cntr_value > 0 OPTION (RECOMPILE);

   -- Things to look at:

   -- How many databases are on the instance?

   -- What recovery models are they using?

   -- What is the log reuse wait description?

   -- How full are the transaction logs?

   -- What compatibility level are the databases on? 

   -- What is the Page Verify Option? (should be CHECKSUM)

   -- Is Auto Update Statistics Asynchronously enabled?

   -- Make sure auto_shrink and auto_close are not enabled!

 

Query #28 Missing Indexes All Databases

 -- Missing Indexes for all databases by Index Advantage 

 SELECT CONVERT(decimal(18,2), user_seeks * avg_total_user_cost * (avg_user_impact * 0.01)) AS [index_advantage], 

 migs.last_user_seek, mid.[statement] AS [Database.Schema.Table],

 mid.equality_columns, mid.inequality_columns, mid.included_columns,

 migs.unique_compiles, migs.user_seeks, migs.avg_total_user_cost, migs.avg_user_impact,

'CREATE INDEX [missing_index_'

+ CONVERT (VARCHAR,mig.index_group_handle) + '_'

+ CONVERT (VARCHAR,mid.index_handle) + '_'

+ LEFT(PARSENAME(mid.statement,1),32) + ']' + ' ON '

+mid.statement

+ ' (' + ISNULL(mid.equality_columns, '')

+ CASE WHEN mid.equality_columns IS NOT NULL

AND mid.inequality_columns IS NOT NULL THEN ','

ELSE ''

END + ISNULL(mid.inequality_columns, '') + ')'

+ ISNULL(' INCLUDE ('

+mid.included_columns

+ ')', '')

AS create_index_statement

 FROM sys.dm_db_missing_index_group_stats AS migs WITH (NOLOCK)

 INNER JOIN sys.dm_db_missing_index_groups AS mig WITH (NOLOCK)

 ON migs.group_handle = mig.index_group_handle

 INNER JOIN sys.dm_db_missing_index_details AS mid WITH (NOLOCK)

 ON mig.index_handle = mid.index_handle

 ORDER BY index_advantage DESC OPTION (RECOMPILE);

 -- Getting missing index information for all of the databases on the instance is very useful

 -- Look at last user seek time, number of user seeks to help determine source and importance

 -- Also look at avg_user_impact and avg_total_user_cost to help determine importance

 -- SQL Server is overly eager to add included columns, so beware

 -- Do not just blindly add indexes that show up from this query!!!

 

Query #29 VLF Counts

   -- Get VLF Counts for all databases on the instance (Query 29) (VLF Counts)

   -- (adapted from Michelle Ufford) 

   CREATE TABLE #VLFInfo (RecoveryUnitID int --FOR 2012 ONWARD, FileID  int,

                          FileSize bigint, StartOffset bigint,

                          FSeqNo      bigint, [Status]    bigint,

                          Parity      bigint, CreateLSN   numeric(38));

 

   CREATE TABLE #VLFCountResults(DatabaseName sysname, VLFCount int);

 

   EXEC sp_MSforeachdb N'Use [?]; 

 

                   INSERT INTO #VLFInfo 

                   EXEC sp_executesql N''DBCC LOGINFO([?])''; 

 

                   INSERT INTO #VLFCountResults 

                   SELECT DB_NAME(), COUNT(*) 

                   FROM #VLFInfo; 

 

                   TRUNCATE TABLE #VLFInfo;'

 

   SELECT DatabaseName, VLFCount  

   FROM #VLFCountResults

   ORDER BY VLFCount DESC;

 

   DROP TABLE #VLFInfo;

   DROP TABLE #VLFCountResults;

   -- High VLF counts can affect write performance 

   -- and they can make full database restores and crash recovery take much longer

   -- Try to keep your VLF counts under 200 in most cases (depending on log file size)

 

   -- Important change to VLF creation algorithm in SQL Server 2014

   -- http://www.sqlskills.com/blogs/paul/important-change-vlf-creation-algorithm-sql-server-2014/

 

Query #30 CPU Usage by Database

-- Get CPU utilization by database

   WITH DB_CPU_Stats

   AS

   (SELECT pa.DatabaseID, DB_Name(pa.DatabaseID) AS [Database Name], SUM(qs.total_worker_time/1000) AS [CPU_Time_Ms]

    FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)

    CROSS APPLY (SELECT CONVERT(int, value) AS [DatabaseID] 

                 FROM sys.dm_exec_plan_attributes(qs.plan_handle)

                 WHERE attribute = N'dbid') AS pa

    GROUP BY DatabaseID)

   SELECT ROW_NUMBER() OVER(ORDER BY [CPU_Time_Ms] DESC) AS [CPU Rank],

          [Database Name], [CPU_Time_Ms] AS [CPU Time (ms)], 

          CAST([CPU_Time_Ms] * 1.0 / SUM([CPU_Time_Ms]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CPU Percent]

   FROM DB_CPU_Stats

   WHERE DatabaseID <> 32767 -- ResourceDB

   ORDER BY [CPU Rank] OPTION (RECOMPILE);

   -- Helps determine which database is using the most CPU resources on the instance

 

Query #31 IO Usage Usage by Database

 -- Get I/O utilization by database

 WITH Aggregate_IO_Statistics

 AS

 (SELECT DB_NAME(database_id) AS [Database Name],

 CAST(SUM(num_of_bytes_read + num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS io_in_mb

 FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS]

 GROUP BY database_id)

 SELECT ROW_NUMBER() OVER(ORDER BY io_in_mb DESC) AS [I/O Rank], [Database Name], io_in_mb AS [Total I/O (MB)],

        CAST(io_in_mb/ SUM(io_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [I/O Percent]

 FROM Aggregate_IO_Statistics

 ORDER BY [I/O Rank] OPTION (RECOMPILE);

-- Helps determine which database is using the most I/O resources on the instance

 

Query #32 Total Buffer Usage Usage by Database

  -- Get total buffer usage by database for current instance

  -- This make take some time to run on a busy instance

  WITH AggregateBufferPoolUsage

  AS

  (SELECT DB_NAME(database_id) AS [Database Name],

  CAST(COUNT(*) * 8/1024.0 AS DECIMAL (10,2))  AS [CachedSize]

  FROM sys.dm_os_buffer_descriptors WITH (NOLOCK)

  WHERE database_id <> 32767 -- ResourceDB

  GROUP BY DB_NAME(database_id))

  SELECT ROW_NUMBER() OVER(ORDER BY CachedSize DESC) AS [Buffer Pool Rank], [Database Name], CachedSize AS [Cached Size (MB)],

         CAST(CachedSize / SUM(CachedSize) OVER() * 100.0 AS DECIMAL(5,2)) AS [Buffer Pool Percent]

  FROM AggregateBufferPoolUsage

  ORDER BY [Buffer Pool Rank] OPTION (RECOMPILE);

  -- Tells you how much memory (in the buffer pool) 

  -- is being used by each database on the instance

 

Query #33 Top Waits

   -- Clear Wait Stats with this command

   -- DBCC SQLPERF('sys.dm_os_wait_stats', CLEAR);

   -- Isolate top waits for server instance since last restart or wait statistics clear  (Query 33) (Top Waits)

   WITH [Waits] 

   AS (SELECT wait_type, wait_time_ms/ 1000.0 AS [WaitS],

             (wait_time_ms - signal_wait_time_ms) / 1000.0 AS [ResourceS],

              signal_wait_time_ms / 1000.0 AS [SignalS],

              waiting_tasks_count AS [WaitCount],

              100.0 *  wait_time_ms / SUM (wait_time_ms) OVER() AS [Percentage],

              ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS [RowNum]

       FROM sys.dm_os_wait_stats WITH (NOLOCK)

       WHERE [wait_type] NOT IN (

           N'BROKER_EVENTHANDLER', N'BROKER_RECEIVE_WAITFOR', N'BROKER_TASK_STOP',

           N'BROKER_TO_FLUSH', N'BROKER_TRANSMITTER', N'CHECKPOINT_QUEUE',

           N'CHKPT', N'CLR_AUTO_EVENT', N'CLR_MANUAL_EVENT', N'CLR_SEMAPHORE',

           N'DBMIRROR_DBM_EVENT', N'DBMIRROR_EVENTS_QUEUE', N'DBMIRROR_WORKER_QUEUE',

           N'DBMIRRORING_CMD', N'DIRTY_PAGE_POLL', N'DISPATCHER_QUEUE_SEMAPHORE',

           N'EXECSYNC', N'FSAGENT', N'FT_IFTS_SCHEDULER_IDLE_WAIT', N'FT_IFTSHC_MUTEX',

           N'HADR_CLUSAPI_CALL', N'HADR_FILESTREAM_IOMGR_IOCOMPLETION', N'HADR_LOGCAPTURE_WAIT', 

           N'HADR_NOTIFICATION_DEQUEUE', N'HADR_TIMER_TASK', N'HADR_WORK_QUEUE',

           N'KSOURCE_WAKEUP', N'LAZYWRITER_SLEEP', N'LOGMGR_QUEUE', 

           N'MEMORY_ALLOCATION_EXT', N'ONDEMAND_TASK_QUEUE',

           N'PREEMPTIVE_OS_LIBRARYOPS', N'PREEMPTIVE_OS_COMOPS', N'PREEMPTIVE_OS_CRYPTOPS',

           N'PREEMPTIVE_OS_PIPEOPS', N'PREEMPTIVE_OS_AUTHENTICATIONOPS',

           N'PREEMPTIVE_OS_GENERICOPS', N'PREEMPTIVE_OS_VERIFYTRUST',

           N'PREEMPTIVE_OS_FILEOPS', N'PREEMPTIVE_OS_DEVICEOPS',

           N'PWAIT_ALL_COMPONENTS_INITIALIZED', N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP',

           N'QDS_ASYNC_QUEUE',

           N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP', N'REQUEST_FOR_DEADLOCK_SEARCH',

           N'RESOURCE_QUEUE', N'SERVER_IDLE_CHECK', N'SLEEP_BPOOL_FLUSH', N'SLEEP_DBSTARTUP',

           N'SLEEP_DCOMSTARTUP', N'SLEEP_MASTERDBREADY', N'SLEEP_MASTERMDREADY',

           N'SLEEP_MASTERUPGRADED', N'SLEEP_MSDBSTARTUP', N'SLEEP_SYSTEMTASK', N'SLEEP_TASK',

           N'SLEEP_TEMPDBSTARTUP', N'SNI_HTTP_ACCEPT', N'SP_SERVER_DIAGNOSTICS_SLEEP',

           N'SQLTRACE_BUFFER_FLUSH', N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP', N'SQLTRACE_WAIT_ENTRIES',

           N'WAIT_FOR_RESULTS', N'WAITFOR', N'WAITFOR_TASKSHUTDOWN', N'WAIT_XTP_HOST_WAIT',

           N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG', N'WAIT_XTP_CKPT_CLOSE', N'XE_DISPATCHER_JOIN',

           N'XE_DISPATCHER_WAIT', N'XE_LIVE_TARGET_TVF', N'XE_TIMER_EVENT')

       AND waiting_tasks_count > 0)

   SELECT

       MAX (W1.wait_type) AS [WaitType],

       CAST (MAX (W1.WaitS) AS DECIMAL (16,2)) AS [Wait_Sec],

       CAST (MAX (W1.ResourceS) AS DECIMAL (16,2)) AS [Resource_Sec],

       CAST (MAX (W1.SignalS) AS DECIMAL (16,2)) AS [Signal_Sec],

       MAX (W1.WaitCount) AS [Wait Count],

       CAST (MAX (W1.Percentage) AS DECIMAL (5,2)) AS [Wait Percentage],

       CAST ((MAX (W1.WaitS) / MAX (W1.WaitCount)) AS DECIMAL (16,4)) AS [AvgWait_Sec],

       CAST ((MAX (W1.ResourceS) / MAX (W1.WaitCount)) AS DECIMAL (16,4)) AS [AvgRes_Sec],

       CAST ((MAX (W1.SignalS) / MAX (W1.WaitCount)) AS DECIMAL (16,4)) AS [AvgSig_Sec]

   FROM Waits AS W1

   INNER JOIN Waits AS W2

   ON W2.RowNum <= W1.RowNum

   GROUP BY W1.RowNum

   HAVING SUM (W2.Percentage) - MAX (W1.Percentage) < 99 -- percentage threshold

   OPTION (RECOMPILE);

   -- Cumulative wait stats are not as useful on an idle instance that is not under load or performance pressure

 

   -- The SQL Server Wait Type Repository

   -- http://blogs.msdn.com/b/psssql/archive/2009/11/03/the-sql-server-wait-type-repository.aspx

 

   -- Wait statistics, or please tell me where it hurts

   -- http://www.sqlskills.com/blogs/paul/wait-statistics-or-please-tell-me-where-it-hurts/

 

   -- SQL Server 2005 Performance Tuning using the Waits and Queues

   -- http://technet.microsoft.com/en-us/library/cc966413.aspx

 

   -- sys.dm_os_wait_stats (Transact-SQL)

   -- http://msdn.microsoft.com/en-us/library/ms179984(v=sql.120).aspx

 

Query #34 Connection Counts by IP Address

-- Get a count of SQL connections by IP address

 SELECT ec.client_net_address, es.[host_name],es.[program_name], es.login_name, 

 COUNT(ec.session_id) AS [connection count] 

 FROM sys.dm_exec_sessions AS es WITH (NOLOCK) 

 INNER JOIN sys.dm_exec_connections AS ec WITH (NOLOCK) 

 ON es.session_id = ec.session_id 

 GROUP BY ec.client_net_address, es.[program_name], es.[host_name], es.login_name  

 ORDER BY ec.client_net_address, es.[program_name] OPTION (RECOMPILE);

 -- This helps you figure where your database load is coming from

 -- and verifies connectivity from other machines

 

Query #35 Avg Task Counts

  -- Get Average Task Counts

  SELECT AVG(current_tasks_count) AS [Avg Task Count], 

  AVG(work_queue_count) AS [Avg Work Queue Count],

  AVG(runnable_tasks_count) AS [Avg Runnable Task Count],

  AVG(pending_disk_io_count) AS [Avg Pending DiskIO Count]

  FROM sys.dm_os_schedulers WITH (NOLOCK)

  WHERE scheduler_id < 255 OPTION (RECOMPILE);

  -- Sustained values above 10 suggest further investigation in that area

  -- High Avg Task Counts are often caused by blocking/deadlocking or other resource contention

  -- Sustained values above 1 suggest further investigation in that area

  -- High Avg Runnable Task Counts are a good sign of CPU pressure

  -- High Avg Pending DiskIO Counts are a sign of disk pressure

 

Query #36 Detect Blocking

 -- Detect blocking (run multiple times)

 SELECT t1.resource_type AS [lock type], DB_NAME(resource_database_id) AS [database],

 t1.resource_associated_entity_id AS [blk object],t1.request_mode AS [lock req],  --- lock requested

 t1.request_session_id AS [waiter sid], t2.wait_duration_ms AS [wait time],       -- spid of waiter  

 (SELECT text FROM sys.dm_exec_requests AS r WITH (NOLOCK)                      -- get sql for waiter

 CROSS APPLY sys.dm_exec_sql_text(r.[sql_handle]) 

 WHERE r.session_id = t1.request_session_id) AS [waiter_batch],

 (SELECT SUBSTRING(qt.text,r.statement_start_offset/2, 

     (CASE WHEN r.statement_end_offset = -1 

     THEN LEN(CONVERT(nvarchar(max), qt.text)) * 2 

     ELSE r.statement_end_offset END - r.statement_start_offset)/2) 

 FROM sys.dm_exec_requests AS r WITH (NOLOCK)

 CROSS APPLY sys.dm_exec_sql_text(r.[sql_handle]) AS qt

 WHERE r.session_id = t1.request_session_id) AS [waiter_stmt],                    -- statement blocked

 t2.blocking_session_id AS [blocker sid],                                        -- spid of blocker

 (SELECT text FROM sys.sysprocesses AS p                                        -- get sql for blocker

 CROSS APPLY sys.dm_exec_sql_text(p.[sql_handle]) 

 WHERE p.spid = t2.blocking_session_id) AS [blocker_batch]

 FROM sys.dm_tran_locks AS t1 WITH (NOLOCK)

 INNER JOIN sys.dm_os_waiting_tasks AS t2 WITH (NOLOCK)

 ON t1.lock_owner_address = t2.resource_address OPTION (RECOMPILE);

 -- Helps troubleshoot blocking and deadlocking issues

 -- The results will change from second to second on a busy system

 -- You should run this query multiple times when you see signs of blocking

 

Query #37 CPU Utilization History

 -- Get CPU Utilization History for last 256 minutes (in one minute intervals)

 -- This version works with SQL Server 2016

 DECLARE @ts_now bigint = (SELECT cpu_ticks/(cpu_ticks/ms_ticks) FROM sys.dm_os_sys_info WITH (NOLOCK)); 

 SELECT TOP(256) SQLProcessUtilization AS [SQL Server Process CPU Utilization], 

                SystemIdle AS [System Idle Process], 

                100 - SystemIdle - SQLProcessUtilization AS [Other Process CPU Utilization], 

                DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) AS [Event Time] 

 FROM (SELECT record.value('(./Record/@id)[1]', 'int') AS record_id, 

             record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') 

             AS [SystemIdle], 

             record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') 

             AS [SQLProcessUtilization], [timestamp] 

       FROM (SELECT [timestamp], CONVERT(xml, record) AS [record] 

             FROM sys.dm_os_ring_buffers WITH (NOLOCK)

             WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' 

             AND record LIKE N'%<SystemHealth>%') AS x) AS y 

 ORDER BY record_id DESC OPTION (RECOMPILE);

 -- Look at the trend over the entire period 

 -- Also look at high sustained Other Process CPU Utilization values

 

Query #38 Top Worker Time Queries

-- Get top total worker time queries for entire instance

SELECT TOP(50) DB_NAME(t.[dbid]) AS [Database Name], LEFT(t.text, 50) AS [Short Query Text],  

qs.total_worker_time AS [Total Worker Time], qs.min_worker_time AS [Min Worker Time],

qs.total_worker_time/qs.execution_count AS [Avg Worker Time], 

qs.max_worker_time AS [Max Worker Time], 

qs.min_elapsed_time AS [Min Elapsed Time], 

qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], 

qs.max_elapsed_time AS [Max Elapsed Time],

qs.min_logical_reads AS [Min Logical Reads],

qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads],

qs.max_logical_reads AS [Max Logical Reads], 

qs.execution_count AS [Execution Count], qs.creation_time AS [Creation Time]

-- ,t. AS [Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel

FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK)

CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t 

CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp 

ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

-- Helps you find the most expensive queries from a CPU perspective across the entire instance

-- Can also help track down parameter sniffing issues

 

Query #39 PLE by NUMA Node

  -- Page Life Expectancy (PLE) value for each NUMA node in current instance

  SELECT @@SERVERNAME AS [Server Name], [object_name], instance_name, cntr_value AS [Page Life Expectancy]

  FROM sys.dm_os_performance_counters WITH (NOLOCK)

  WHERE [object_name] LIKE N'%Buffer Node%' -- Handles named instances

  AND counter_name = N'Page life expectancy' OPTION (RECOMPILE);

  -- PLE is a good measurement of memory pressure

  -- Higher PLE is better. Watch the trend over time, not the absolute value

  -- This will only return one row for non-NUMA systems

  -- Page Life Expectancy isn't what you think

  -- http://www.sqlskills.com/blogs/paul/page-life-expectancy-isnt-what-you-think/

 

Query #40 Memory Grants Pending

-- Memory Grants Pending value for current instance (Query 40) (Memory Grants Pending)

SELECT@@SERVERNAMEAS [Server Name], [object_name], cntr_value AS [Memory Grants Pending]

FROM sys.dm_os_performance_counters WITH (NOLOCK)

WHERE [object_name] LIKE N'%Memory Manager%'-- Handles named instances

AND counter_name = N'Memory Grants Pending'OPTION (RECOMPILE);

-- Run multiple times, and run periodically is you suspect you are under memory pressure

-- Memory Grants Pending above zero for a sustained period is a very strong indicatorof internal memory pressure

你可能感兴趣的:(SQL Server 诊断查询-(3))