zoukankan      html  css  js  c++  java
  • X 使用DMV,诊断和调优DB性能。

    使用DMV,诊断和调优DB性能。
    
    查看等待统计信息,找出SQL Server慢在哪里:
    
    SELECT wait_type ,
    SUM(wait_time_ms / 1000) AS [wait_time_s]
    FROM sys.dm_os_wait_stats DOWS
    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'ONDEMAND_TASK_QUEUE',
            N'PWAIT_ALL_COMPONENTS_INITIALIZED',
            N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP',
            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_TIMER_EVENT')
    GROUP BY wait_type
    ORDER BY SUM(wait_time_ms) DESC
     
     
    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
        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'ONDEMAND_TASK_QUEUE',
            N'PWAIT_ALL_COMPONENTS_INITIALIZED',
            N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP',
            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_TIMER_EVENT')
        AND [waiting_tasks_count] > 0
     )
    SELECT
        MAX ([W1].[wait_type]) AS [WaitType],
        CAST (MAX ([W1].[WaitS]) AS DECIMAL (16,2)) AS [Wait_S],
        CAST (MAX ([W1].[ResourceS]) AS DECIMAL (16,2)) AS [Resource_S],
        CAST (MAX ([W1].[SignalS]) AS DECIMAL (16,2)) AS [Signal_S],
        MAX ([W1].[WaitCount]) AS [WaitCount],
        CAST (MAX ([W1].[Percentage]) AS DECIMAL (5,2)) AS [Percentage],
        CAST ((MAX ([W1].[WaitS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgWait_S],
        CAST ((MAX ([W1].[ResourceS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgRes_S],
        CAST ((MAX ([W1].[SignalS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgSig_S]
    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]) < 95; -- percentage threshold
    GO
    获取一段时间内累计的File reads:
    
    
    
    SELECT DB_NAME(mf.database_id) AS databaseName ,
    mf.physical_name ,
    divfs.num_of_reads ,
    --other columns removed in this section. See Listing 6.14 for complete code
    GETDATE() AS baselineDate
    INTO #baseline
    FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    JOIN sys.master_files AS mf ON mf.database_id = divfs.database_id
    AND mf.file_id = divfs.file_id
     
    --过一段时间后执行下面的SQL
     
    WITH currentLine
    AS ( SELECT DB_NAME(mf.database_id) AS databaseName ,
    mf.physical_name ,
    num_of_reads ,
    --other columms removed
    GETDATE() AS currentlineDate
    FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    JOIN sys.master_files AS mf
    ON mf.database_id = divfs.database_id
    AND mf.file_id = divfs.file_id
    )
    SELECT currentLine.databaseName ,
    currentLine.physical_name ,
    --gets the time difference in milliseconds since the baseline was taken
    DATEDIFF(millisecond,baseLineDate,currentLineDate) AS elapsed_ms,
    --gets the change in time since the baseline was taken
    currentLine.num_of_reads - #baseline.num_of_reads AS num_of_reads
    --other columns removed
    FROM currentLine
    INNER JOIN #baseline ON #baseLine.databaseName = currentLine.databaseName
    AND #baseLine.physical_name = currentLine.physical_name
    根据IP获取连接个数
    
    -- Get a count of SQL connections by IP address
    SELECT dec.client_net_address ,
    des.program_name ,
    des.host_name ,
    --des.login_name ,
    COUNT(dec.session_id) AS connection_count
    FROM sys.dm_exec_sessions AS des
    INNER JOIN sys.dm_exec_connections AS dec
    ON des.session_id = dec.session_id
    -- WHERE LEFT(des.host_name, 2) = 'WK'
    GROUP BY dec.client_net_address ,
    des.program_name ,
    des.host_name
    -- des.login_name
    -- HAVING COUNT(dec.session_id) > 1
    ORDER BY des.program_name,
    dec.client_net_address ;
    查看谁在通过SSMS执行什么
    
    SELECT dec.client_net_address ,
    des.host_name ,
    dest.text
    FROM sys.dm_exec_sessions des
    INNER JOIN sys.dm_exec_connections dec
    ON des.session_id = dec.session_id
    CROSS APPLY sys.dm_exec_sql_text(dec.most_recent_sql_handle) dest
    WHERE des.program_name LIKE 'Microsoft SQL Server Management Studio%'
    ORDER BY des.program_name ,
    dec.client_net_address
    查看当前session的session级别的设置
    SELECT des.text_size ,
    des.language ,
    des.date_format ,
    des.date_first ,
    des.quoted_identifier ,
    des.arithabort ,
    des.ansi_null_dflt_on ,
    des.ansi_defaults ,
    des.ansi_warnings ,
    des.ansi_padding ,
    des.ansi_nulls ,
    des.concat_null_yields_null ,
    des.transaction_isolation_level ,
    des.lock_timeout ,
    des.deadlock_priority
    FROM sys.dm_exec_sessions des
    WHERE des.session_id = @@SPID
    查看超过一个session的登录信息
    
    SELECT login_name ,
    COUNT(session_id) AS session_count
    FROM sys.dm_exec_sessions
    WHERE is_user_process = 1
    GROUP BY login_name
    ORDER BY login_name
    识别有context swithing的sessions信息
    
    SELECT session_id ,
    login_name ,
    original_login_name
    FROM sys.dm_exec_sessions
    WHERE is_user_process = 1
    AND login_name <> original_login_name
    识别不活动的sessions
    
    DECLARE @days_old SMALLINT
    SELECT @days_old = 5
    SELECT des.session_id ,
    des.login_time ,
    des.last_request_start_time ,
    des.last_request_end_time ,
    des.[status] ,
    des.[program_name] ,
    des.cpu_time ,
    des.total_elapsed_time ,
    des.memory_usage ,
    des.total_scheduled_time ,
    des.total_elapsed_time ,
    des.reads ,
    des.writes ,
    des.logical_reads ,
    des.row_count ,
    des.is_user_process
    FROM sys.dm_exec_sessions des
    INNER JOIN sys.dm_tran_session_transactions dtst
    ON des.session_id = dtst.session_id
    WHERE des.is_user_process = 1
    AND DATEDIFF(dd, des.last_request_end_time, GETDATE()) > @days_old
    AND des.status != 'Running'
    ORDER BY des.last_request_end_time
    识别孤立事务引起的闲置sessions
    
    SELECT des.session_id ,
    des.login_time ,
    des.last_request_start_time ,
    des.last_request_end_time ,
    des.host_name ,
    des.login_name
    FROM sys.dm_exec_sessions des
    INNER JOIN sys.dm_tran_session_transactions dtst
    ON des.session_id = dtst.session_id
    LEFT JOIN sys.dm_exec_requests der
    ON dtst.session_id = der.session_id
    WHERE der.session_id IS NULL
    ORDER BY des.session_id
    查看当前活动请求的执行计划、CPU消耗等
    
    SELECT der.session_id ,
    DB_NAME(der.database_id) AS database_name ,
    deqp.query_plan ,
    SUBSTRING(dest.text, der.statement_start_offset / 2,
    ( CASE WHEN der.statement_end_offset = -1
    THEN DATALENGTH(dest.text)
    ELSE der.statement_end_offset
    END - der.statement_start_offset ) / 2)
    AS [statement executing] ,
    der.cpu_time
    --der.granted_query_memory
    --der.wait_time
    --der.total_elapsed_time
    --der.reads
    FROM sys.dm_exec_requests der
    INNER JOIN sys.dm_exec_sessions des
    ON des.session_id = der.session_id
    CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) dest
    CROSS APPLY sys.dm_exec_query_plan(der.plan_handle) deqp
    WHERE des.is_user_process = 1
    AND der.session_id <> @@spid
    ORDER BY der.cpu_time DESC ;
    -- ORDER BY der.granted_query_memory DESC ;
    -- ORDER BY der.wait_time DESC;
    -- ORDER BY der.total_elapsed_time DESC;
    -- ORDER BY der.reads DESC;
    查看当前谁在运行什么
    
    -- Who is running what at this instant
    SELECT dest.text AS [Command text] ,
    des.login_time ,
    des.[host_name] ,
    des.[program_name] ,
    der.session_id ,
    dec.client_net_address ,
    der.status ,
    der.command ,
    DB_NAME(der.database_id) AS DatabaseName
    FROM sys.dm_exec_requests der
    INNER JOIN sys.dm_exec_connections dec
    ON der.session_id = dec.session_id
    INNER JOIN sys.dm_exec_sessions des
    ON des.session_id = der.session_id
    CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS dest
    WHERE des.is_user_process = 1
    比SP_WHO2更好的SQL
    
    SELECT des.session_id ,
    des.status ,
    des.login_name ,
    des.[HOST_NAME] ,
    der.blocking_session_id ,
    DB_NAME(der.database_id) AS database_name ,
    der.command ,
    des.cpu_time ,
    des.reads ,
    des.writes ,
    dec.last_write ,
    des.[program_name] ,
    der.wait_type ,
    der.wait_time ,
    der.last_wait_type ,
    der.wait_resource ,
    CASE des.transaction_isolation_level
    WHEN 0 THEN 'Unspecified'
    WHEN 1 THEN 'ReadUncommitted'
    WHEN 2 THEN 'ReadCommitted'
    WHEN 3 THEN 'Repeatable'
    WHEN 4 THEN 'Serializable'
    WHEN 5 THEN 'Snapshot'
    END AS transaction_isolation_level ,
    OBJECT_NAME(dest.objectid, der.database_id) AS OBJECT_NAME ,
    SUBSTRING(dest.text, der.statement_start_offset / 2,
    ( CASE WHEN der.statement_end_offset = -1
    THEN DATALENGTH(dest.text)
    ELSE der.statement_end_offset
    END - der.statement_start_offset ) / 2)
    AS [executing statement] ,
    deqp.query_plan
    FROM sys.dm_exec_sessions des
    LEFT JOIN sys.dm_exec_requests der
    ON des.session_id = der.session_id
    LEFT JOIN sys.dm_exec_connections dec
    ON des.session_id = dec.session_id
    CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) dest
    CROSS APPLY sys.dm_exec_query_plan(der.plan_handle) deqp
    WHERE des.session_id <> @@SPID
    ORDER BY des.session_id
    清除指定数据库的计划缓存
    
    --Determine the id of your database
    DECLARE @intDBID INTEGER
    SET @intDBID = ( SELECT dbid
    FROM master.dbo.sysdatabases
    WHERE name = 'mydatabasename'
    )
    --Flush the procedure cache for your database
    DBCC FLUSHPROCINDB (@intDBID)
    Retrieving the text for a currently executing ad hoc query
    
    SELECT dest.text ,
    dest.dbid ,
    dest.objectid
    FROM sys.dm_exec_requests AS der
    CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) AS dest
    WHERE session_id = @@spid ;
    Retrieving the text for a currently executing batch
    SELECT dest.text
    FROM sys.dm_exec_requests AS der
    CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) AS dest
    WHERE session_id <> @@spid
    AND text LIKE '%waitfor%' ;
    Returning the text of an executing stored procedure
    SELECT dest.dbid ,
    dest.objectid ,
    dest.encrypted ,
    dest.text
    FROM sys.dm_exec_requests AS der
    CROSS APPLY sys.dm_exec_sql_text(der.sql_handle)
    AS dest
    WHERE objectid = object_id('test', 'p');
    
    Parsing the SQL text using statement_start_offset and statement_end_offset
    SELECT der.statement_start_offset ,
    der.statement_end_offset ,
    SUBSTRING(dest.text, der.statement_start_offset / 2,
    ( CASE WHEN der.statement_end_offset = -1
    THEN DATALENGTH(dest.text)
    ELSE der.statement_end_offset
    END - der.statement_start_offset ) / 2)
    AS statement_executing ,
    dest.text AS [full statement code]
    FROM sys.dm_exec_requests der
    INNER JOIN sys.dm_exec_sessions des
    ON des.session_id = der.session_id
    CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) dest
    WHERE des.is_user_process = 1
    AND der.session_id <> @@spid
    ORDER BY der.session_id ;
    
    Investigating offsets.
    WAITFOR DELAY '00:01' ;
    BEGIN TRANSACTION
    -- WAITFOR DELAY '00:01' ;
    INSERT INTO AdventureWorks.Production.ProductCategory
    ( Name, ModifiedDate )
    VALUES ( 'Reflectors', GETDATE() )
    ROLLBACK TRANSACTION
    SELECT Name ,
    ModifiedDate
    FROM AdventureWorks.Production.ProductCategory
    WHERE Name = 'Reflectors' ;
    -- WAITFOR DELAY '00:01' ;
    
    Requests by CPU consumption
    SELECT der.session_id ,
    DB_NAME(der.database_id) AS database_name ,
    deqp.query_plan ,
    SUBSTRING(dest.text, der.statement_start_offset / 2,
    ( CASE WHEN der.statement_end_offset = -1
    THEN DATALENGTH(dest.text)
    ELSE der.statement_end_offset
    END - der.statement_start_offset ) / 2)
    AS [statement executing] ,
    der.cpu_time
    --der.granted_query_memory
    --der.wait_time
    --der.total_elapsed_time
    --der.reads
    FROM sys.dm_exec_requests der
    INNER JOIN sys.dm_exec_sessions des
    ON des.session_id = der.session_id
    CROSS APPLY sys.dm_exec_sql_text(der.sql_handle) dest
    CROSS APPLY sys.dm_exec_query_plan(der.plan_handle) deqp
    WHERE des.is_user_process = 1
    AND der.session_id <> @@spid
    ORDER BY der.cpu_time DESC ;
    -- ORDER BY der.granted_query_memory DESC ;
    -- ORDER BY der.wait_time DESC;
    -- ORDER BY der.total_elapsed_time DESC;
    -- ORDER BY der.reads DESC;
    Who is running what
    
    -- Who is running what at this instant
    SELECT dest.text AS [Command text] ,
    des.login_time ,
    des.[host_name] ,
    des.[program_name] ,
    der.session_id ,
    dec.client_net_address ,
    der.status ,
    der.command ,
    DB_NAME(der.database_id) AS DatabaseName
    FROM sys.dm_exec_requests der
    INNER JOIN sys.dm_exec_connections dec
    ON der.session_id = dec.session_id
    INNER JOIN sys.dm_exec_sessions des
    ON des.session_id = der.session_id
    CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS dest
    WHERE des.is_user_process = 1
    
    Flushing the cache of plans belonging to a particular database.
    
    --Determine the id of your database
    DECLARE @intDBID INTEGER
    SET @intDBID = ( SELECT dbid
    FROM master.dbo.sysdatabases
    WHERE name = 'mydatabasename'
    )
    --Flush the procedure cache for your database
    DBCC FLUSHPROCINDB (@intDBID)
    
    Retrieving the query plan for a cached stored procedure
    CREATE PROCEDURE ShowQueryText
    AS
    SELECT TOP 10
    object_id ,
    name
    FROM sys.objects ;
    --waitfor delay '00:00:00'
     
    SELECT TOP 10
    object_id ,
    name
    FROM sys.objects ;
    SELECT TOP 10
    object_id ,
    name
    FROM sys.procedures ;
    GO
    EXEC dbo.ShowQueryText ;
    GO
    SELECT deqp.dbid ,
    deqp.objectid ,
    deqp.encrypted ,
    deqp.query_plan
    FROM sys.dm_exec_query_stats deqs
    CROSS APPLY sys.dm_exec_query_plan(deqs.plan_handle) AS deqp
    WHERE objectid = OBJECT_ID('ShowQueryText', 'p') ;
    
    Viewing the sql_handle and plan_handle.
    SELECT deqs.plan_handle ,
    deqs.sql_handle ,
    execText.text
    FROM sys.dm_exec_query_stats deqs
    CROSS APPLY sys.dm_exec_sql_text(deqs.plan_handle) AS execText
    WHERE execText.text LIKE 'CREATE PROCEDURE ShowQueryText%'
    
    Extracting the SQL text for individual queries in a batch.
    SELECT CHAR(13) + CHAR(10)
    + CASE WHEN deqs.statement_start_offset = 0
    AND deqs.statement_end_offset = -1
    THEN '-- see objectText column--'
    ELSE '-- query --' + CHAR(13) + CHAR(10)
    + SUBSTRING(execText.text, deqs.statement_start_offset / 2,
    ( ( CASE WHEN deqs.statement_end_offset = -1
    THEN DATALENGTH(execText.text)
    ELSE deqs.statement_end_offset
    END ) - deqs.statement_start_offset ) / 2)
    END AS queryText ,
    deqp.query_plan
    FROM sys.dm_exec_query_stats deqs
    CROSS APPLY sys.dm_exec_sql_text(deqs.plan_handle) AS execText
    CROSS APPLY sys.dm_exec_query_plan(deqs.plan_handle) deqp
    WHERE execText.text LIKE 'CREATE PROCEDURE ShowQueryText%'
    
    Returning the plan using sys.dm_exec_text_query_plan.
    SELECT deqp.dbid ,
    deqp.objectid ,
    CAST(detqp.query_plan AS XML) AS singleStatementPlan ,
    deqp.query_plan AS batch_query_plan ,
    --this won't actually work in all cases because nominal plans aren't
    -- cached, so you won't see a plan for waitfor if you uncomment it
    ROW_NUMBER() OVER ( ORDER BY Statement_Start_offset )
    AS query_position ,
    CASE WHEN deqs.statement_start_offset = 0
    AND deqs.statement_end_offset = -1
    THEN '-- see objectText column--'
    ELSE '-- query --' + CHAR(13) + CHAR(10)
    + SUBSTRING(execText.text, deqs.statement_start_offset / 2,
    ( ( CASE WHEN deqs.statement_end_offset = -1
    THEN DATALENGTH(execText.text)
    ELSE deqs.statement_end_offset
    END ) - deqs.statement_start_offset ) / 2)
    END AS queryText
    FROM sys.dm_exec_query_stats deqs
    CROSS APPLY sys.dm_exec_text_query_plan(deqs.plan_handle,
    deqs.statement_start_offset,
    deqs.statement_end_offset)
    AS detqp
    CROSS APPLY sys.dm_exec_query_plan(deqs.plan_handle) AS deqp
    CROSS APPLY sys.dm_exec_sql_text(deqs.plan_handle) AS execText
    WHERE deqp.objectid = OBJECT_ID('ShowQueryText', 'p') ;
    
    Retrieving the plans for compiled objects.
    SELECT refcounts ,
    usecounts ,
    size_in_bytes ,
    cacheobjtype ,
    objtype
    FROM sys.dm_exec_cached_plans
    WHERE objtype IN ( 'proc', 'prepared' ) ;
    
    Total number of cached plans.
    SELECT COUNT(*)
    FROM sys.dm_exec_cached_plans ;
    
    An overview of plan reuse.
    SELECT MAX(CASE WHEN usecounts BETWEEN 10 AND 100 THEN '10-100'
    WHEN usecounts BETWEEN 101 AND 1000 THEN '101-1000'
    WHEN usecounts BETWEEN 1001 AND 5000 THEN '1001-5000'
    WHEN usecounts BETWEEN 5001 AND 10000 THEN '5001-10000'
    ELSE CAST(usecounts AS VARCHAR(100))
    END) AS usecounts ,
    COUNT(*) AS countInstance
    FROM sys.dm_exec_cached_plans
    GROUP BY CASE WHEN usecounts BETWEEN 10 AND 100 THEN 50
    WHEN usecounts BETWEEN 101 AND 1000 THEN 500
    WHEN usecounts BETWEEN 1001 AND 5000 THEN 2500
    WHEN usecounts BETWEEN 5001 AND 10000 THEN 7500
    ELSE usecounts
    END
    ORDER BY CASE WHEN usecounts BETWEEN 10 AND 100 THEN 50
    WHEN usecounts BETWEEN 101 AND 1000 THEN 500
    WHEN usecounts BETWEEN 1001 AND 5000 THEN 2500
    WHEN usecounts BETWEEN 5001 AND 10000 THEN 7500
    ELSE usecounts
    END DESC ;
    
    Investigating the most used plans.
    SELECT TOP 2 WITH TIES
    decp.usecounts ,
    decp.cacheobjtype ,
    decp.objtype ,
    deqp.query_plan ,
    dest.text
    FROM sys.dm_exec_cached_plans decp
    CROSS APPLY sys.dm_exec_query_plan(decp.plan_handle) AS deqp
    CROSS APPLY sys.dm_exec_sql_text(decp.plan_handle) AS dest
    ORDER BY usecounts DESC ;
    
    Examining plan reuse for a single procedure
     SELECT usecounts ,
    cacheobjtype ,
    objtype ,
    OBJECT_NAME(dest.objectid)
    FROM sys.dm_exec_cached_plans decp
    CROSS APPLY sys.dm_exec_sql_text(decp.plan_handle) AS dest
    WHERE dest.objectid = OBJECT_ID('<procedureName>')
    AND dest.dbid = DB_ID()
    ORDER BY usecounts DESC ;
    
    Examining single-use plans in the cache
    -- Find single-use, ad hoc queries that are bloating the plan cache
    SELECT TOP ( 100 )
    [text] ,
    cp.size_in_bytes
    FROM sys.dm_exec_cached_plans AS cp
    CROSS APPLY sys.dm_exec_sql_text(plan_handle)
    WHERE cp.cacheobjtype = 'Compiled Plan'
    AND cp.objtype = 'Adhoc'
    AND cp.usecounts = 1
    ORDER BY cp.size_in_bytes DESC ;
    
    Examining plan attributes.
    SELECT CAST(depa.attribute AS VARCHAR(30)) AS attribute ,
    CAST(depa.value AS VARCHAR(30)) AS value ,
    depa.is_cache_key
    FROM ( SELECT TOP 1
    *
    FROM sys.dm_exec_cached_plans
    ORDER BY usecounts DESC
    ) decp
    OUTER APPLY sys.dm_exec_plan_attributes(decp.plan_handle) depa
    WHERE is_cache_key = 1
    ORDER BY usecounts DESC ;
    
    Finding the CPU-intensive queries.
     SELECT TOP 3
    total_worker_time ,
    execution_count ,
    total_worker_time / execution_count AS [Avg CPU Time] ,
    CASE WHEN deqs.statement_start_offset = 0
    AND deqs.statement_end_offset = -1
    THEN '-- see objectText column--'
    ELSE '-- query --' + CHAR(13) + CHAR(10)
    + SUBSTRING(execText.text, deqs.statement_start_offset / 2,
    ( ( CASE WHEN deqs.statement_end_offset = -1
    THEN DATALENGTH(execText.text)
    ELSE deqs.statement_end_offset
    END ) - deqs.statement_start_offset ) / 2)
    END AS queryText
    FROM sys.dm_exec_query_stats deqs
    CROSS APPLY sys.dm_exec_sql_text(deqs.plan_handle) AS execText
    ORDER BY deqs.total_worker_time DESC ;
    
    Grouping by sql_handle to see query stats at the batch level.
    SELECT TOP 100
    SUM(total_logical_reads) AS total_logical_reads ,
    COUNT(*) AS num_queries , --number of individual queries in batch
    --not all usages need be equivalent, in the case of looping
    --or branching code
    MAX(execution_count) AS execution_count ,
    MAX(execText.text) AS queryText
    FROM sys.dm_exec_query_stats deqs
    CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS execText
    GROUP BY deqs.sql_handle
    HAVING AVG(total_logical_reads / execution_count) <> SUM(total_logical_reads)
    / SUM(execution_count)
    ORDER BY 1 DESC
    
    Investigating logical reads performed by cached stored procedures.
    -- Top Cached SPs By Total Logical Reads (SQL 2008 only).
    -- Logical reads relate to memory pressure
    SELECT TOP ( 25 )
    p.name AS [SP Name] ,
    deps.total_logical_reads AS [TotalLogicalReads] ,
    deps.total_logical_reads / deps.execution_count AS [AvgLogicalReads] ,
    deps.execution_count ,
    ISNULL(deps.execution_count / DATEDIFF(Second, deps.cached_time,
    GETDATE()), 0) AS [Calls/Second] ,
    deps.total_elapsed_time ,
    deps.total_elapsed_time / deps.execution_count AS [avg_elapsed_time] ,
    deps.cached_time
    FROM sys.procedures AS p
    INNER JOIN sys.dm_exec_procedure_stats
    AS deps ON p.[object_id] = deps.[object_id]
    WHERE deps.database_id = DB_ID()
    ORDER BY deps.total_logical_reads DESC ;
    
    Examine optimizer counters.
    SELECT counter ,
    occurrence ,
    value
    FROM sys.dm_exec_query_optimizer_info
    WHERE counter IN ( 'optimizations', 'elapsed time', 'final cost' ) ;
    Trivial changes to query text can affect plan reuse.
    SELECT COUNTER ,
    OCCURRENCE ,
    VALUE
    FROM SYS.DM_EXEC_QUERY_OPTIMIZER_INFO
    WHERE COUNTER IN ( 'optimizations', 'elapsed time', 'final cost' ) ;
    
    Locking due to single UPDATE statement against a user table in SQL Server
    SELECT [resource_type] ,
    DB_NAME([resource_database_id]) AS [Database Name] ,
    CASE WHEN DTL.resource_type IN ( 'DATABASE', 'FILE', 'METADATA' )
    THEN DTL.resource_type
    WHEN DTL.resource_type = 'OBJECT'
    THEN OBJECT_NAME(DTL.resource_associated_entity_id,
    DTL.[resource_database_id])
    WHEN DTL.resource_type IN ( 'KEY', 'PAGE', 'RID' )
    THEN ( SELECT OBJECT_NAME([object_id])
    FROM sys.partitions
    WHERE sys.partitions.hobt_id =
    DTL.resource_associated_entity_id
    )
    ELSE 'Unidentified'
    END AS requested_object_name ,
    [request_mode] ,
    [resource_description]
    FROM sys.dm_tran_locks DTL
    WHERE DTL.[resource_type] <> 'DATABASE' ;
    
    Which sessions are causing blocking and what statement are they running?
    SELECT DTL.[request_session_id] AS [session_id] ,
    DB_NAME(DTL.[resource_database_id]) AS [Database] ,
    DTL.resource_type ,
    CASE WHEN DTL.resource_type IN ( 'DATABASE', 'FILE', 'METADATA' )
    THEN DTL.resource_type
    WHEN DTL.resource_type = 'OBJECT'
    THEN OBJECT_NAME(DTL.resource_associated_entity_id,
    DTL.[resource_database_id])
    WHEN DTL.resource_type IN ( 'KEY', 'PAGE', 'RID' )
    THEN ( SELECT OBJECT_NAME([object_id])
    FROM sys.partitions
    WHERE sys.partitions.hobt_id =
    DTL.resource_associated_entity_id
    )
    ELSE 'Unidentified'
    END AS [Parent Object] ,
    DTL.request_mode AS [Lock Type] ,
    DTL.request_status AS [Request Status] ,
    DER.[blocking_session_id] ,
    DES.[login_name] ,
    CASE DTL.request_lifetime
    WHEN 0 THEN DEST_R.TEXT
    ELSE DEST_C.TEXT
    END AS [Statement]
    FROM sys.dm_tran_locks DTL
    LEFT JOIN sys.[dm_exec_requests] DER
    ON DTL.[request_session_id] = DER.[session_id]
    INNER JOIN sys.dm_exec_sessions DES
    ON DTL.request_session_id = DES.[session_id]
    INNER JOIN sys.dm_exec_connections DEC
    ON DTL.[request_session_id] = DEC.[most_recent_session_id]
    OUTER APPLY sys.dm_exec_sql_text(DEC.[most_recent_sql_handle])
    AS DEST_C
    OUTER APPLY sys.dm_exec_sql_text(DER.sql_handle) AS DEST_R
    WHERE DTL.[resource_database_id] = DB_ID()
    AND DTL.[resource_type] NOT IN ( 'DATABASE', 'METADATA' )
    ORDER BY DTL.[request_session_id] ;
    
    Investigating locking and blocking based on waiting tasks.
    SELECT DTL.[resource_type] AS [resource type] ,
    CASE WHEN DTL.[resource_type] IN ( 'DATABASE', 'FILE', 'METADATA' )
    THEN DTL.[resource_type]
    WHEN DTL.[resource_type] = 'OBJECT'
    THEN OBJECT_NAME(DTL.resource_associated_entity_id)
    WHEN DTL.[resource_type] IN ( 'KEY', 'PAGE', 'RID' )
    THEN ( SELECT OBJECT_NAME([object_id])
    FROM sys.partitions
    WHERE sys.partitions.[hobt_id] =
    DTL.[resource_associated_entity_id]
    )
    ELSE 'Unidentified'
    END AS [Parent Object] ,
    DTL.[request_mode] AS [Lock Type] ,
    DTL.[request_status] AS [Request Status] ,
    DOWT.[wait_duration_ms] AS [wait duration ms] ,
    DOWT.[wait_type] AS [wait type] ,
    DOWT.[session_id] AS [blocked session id] ,
    DES_blocked.[login_name] AS [blocked_user] ,
    SUBSTRING(dest_blocked.text, der.statement_start_offset / 2,
    ( CASE WHEN der.statement_end_offset = -1
    THEN DATALENGTH(dest_blocked.text)
    ELSE der.statement_end_offset
    END - der.statement_start_offset ) / 2
    AS [blocked_command] ,
    DOWT.[blocking_session_id] AS [blocking session id] ,
    DES_blocking.[login_name] AS [blocking user] ,
    DEST_blocking.[text] AS [blocking command] ,
    DOWT.resource_description AS [blocking resource detail]
    FROM sys.dm_tran_locks DTL
    INNER JOIN sys.dm_os_waiting_tasks DOWT
    ON DTL.lock_owner_address = DOWT.resource_address
    INNER JOIN sys.[dm_exec_requests] DER
    ON DOWT.[session_id] = DER.[session_id]
    INNER JOIN sys.dm_exec_sessions DES_blocked
    ON DOWT.[session_id] = DES_Blocked.[session_id]
    INNER JOIN sys.dm_exec_sessions DES_blocking
    ON DOWT.[blocking_session_id] = DES_Blocking.[session_id]
    INNER JOIN sys.dm_exec_connections DEC
    ON DTL.[request_session_id] = DEC.[most_recent_session_id]
    CROSS APPLY sys.dm_exec_sql_text(DEC.[most_recent_sql_handle])
    AS DEST_Blocking
    CROSS APPLY sys.dm_exec_sql_text(DER.sql_handle) AS DEST_Blocked
    WHERE DTL.[resource_database_id] = DB_ID()
    
    Querying sys.dm_db_tran_active_transactions
     SELECT DTAT.transaction_id ,
    DTAT.[name] ,
    DTAT.transaction_begin_time ,
    CASE DTAT.transaction_type
    WHEN 1 THEN 'Read/write'
    WHEN 2 THEN 'Read-only'
    WHEN 3 THEN 'System'
    WHEN 4 THEN 'Distributed'
    END AS transaction_type ,
    CASE DTAT.transaction_state
    WHEN 0 THEN 'Not fully initialized'
    WHEN 1 THEN 'Initialized, not started'
    WHEN 2 THEN 'Active'
    WHEN 3 THEN 'Ended' -- only applies to read-only transactions
    WHEN 4 THEN 'Commit initiated'-- distributed transactions only
    WHEN 5 THEN 'Prepared, awaiting resolution'
    WHEN 6 THEN 'Committed'
    WHEN 7 THEN 'Rolling back'
    WHEN 8 THEN 'Rolled back'
    END AS transaction_state ,
    CASE DTAT.dtc_state
    WHEN 1 THEN 'Active'
    WHEN 2 THEN 'Prepared'
    WHEN 3 THEN 'Committed'
    WHEN 4 THEN 'Aborted'
    WHEN 5 THEN 'Recovered'
    END AS dtc_state
    FROM sys.dm_tran_active_transactions DTAT
    INNER JOIN sys.dm_tran_session_transactions DTST
    ON DTAT.transaction_id = DTST.transaction_id
    WHERE [DTST].[is_user_transaction] = 1
    ORDER BY DTAT.transaction_begin_time
    Eliminating worktables from the results returned by active_transactions.
    FROM sys.dm_tran_active_transactions DTAT
    WHERE DTAT.name <> 'worktable'
    ORDER BY DTAT.transaction_begin_time
    Decoding the integer values returned by database_transaction_state.
    
    CASE SDTDT.database_transaction_state
    WHEN 1 THEN 'Not initialized'
    WHEN 3 THEN 'initialized, but not producing log records'
    WHEN 4 THEN 'Producing log records'
    WHEN 5 THEN 'Prepared'
    WHEN 10 THEN 'Committed'
    WHEN 11 THEN 'Rolled back'
    WHEN 12 THEN 'Commit in process'
    
    Transaction log impact of active transactions.
    
    SELECT DTST.[session_id],
    DES.[login_name] AS [Login Name],
    DB_NAME (DTDT.database_id) AS [Database],
    DTDT.[database_transaction_begin_time] AS [Begin Time],
    -- DATEDIFF(ms,DTDT.[database_transaction_begin_time], GETDATE()) AS [Duration
    ms],
    CASE DTAT.transaction_type
    WHEN 1 THEN 'Read/write'
    WHEN 2 THEN 'Read-only'
    WHEN 3 THEN 'System'
    WHEN 4 THEN 'Distributed'
    END AS [Transaction Type],
    CASE DTAT.transaction_state
    WHEN 0 THEN 'Not fully initialized'
    WHEN 1 THEN 'Initialized, not started'
    WHEN 2 THEN 'Active'
    WHEN 3 THEN 'Ended'
    WHEN 4 THEN 'Commit initiated'
    WHEN 5 THEN 'Prepared, awaiting resolution'
    WHEN 6 THEN 'Committed'
    WHEN 7 THEN 'Rolling back'
    WHEN 8 THEN 'Rolled back'
    END AS [Transaction State],
    DTDT.[database_transaction_log_record_count] AS [Log Records],
    DTDT.[database_transaction_log_bytes_used] AS [Log Bytes Used],
    DTDT.[database_transaction_log_bytes_reserved] AS [Log Bytes RSVPd],
    DEST.[text] AS [Last Transaction Text],
    DEQP.[query_plan] AS [Last Query Plan]
    FROM sys.dm_tran_database_transactions DTDT
    INNER JOIN sys.dm_tran_session_transactions DTST
    ON DTST.[transaction_id] = DTDT.[transaction_id]
    INNER JOIN sys.[dm_tran_active_transactions] DTAT
    ON DTST.[transaction_id] = DTAT.[transaction_id]
    INNER JOIN sys.[dm_exec_sessions] DES
    ON DES.[session_id] = DTST.[session_id]
    INNER JOIN sys.dm_exec_connections DEC
    ON DEC.[session_id] = DTST.[session_id]
    LEFT JOIN sys.dm_exec_requests DER
    ON DER.[session_id] = DTST.[session_id]
    CROSS APPLY sys.dm_exec_sql_text (DEC.[most_recent_sql_handle]) AS DEST
    OUTER APPLY sys.dm_exec_query_plan (DER.[plan_handle]) AS DEQP
    ORDER BY DTDT.[database_transaction_log_bytes_used] DESC;
    -- ORDER BY [Duration ms] DESC;
    
    Which databases are using snapshot isolation
    SELECT SD.[name] ,
    SD.snapshot_isolation_state_desc ,
    SD.is_read_committed_snapshot_on
    FROM sys.databases SD
    WHERE SD.snapshot_isolation_state_desc = 'ON'
    
    Interrogating the active_snapshot_database_transactions DMV
     SELECT DTASDT.transaction_id ,
    DTASDT.session_id ,
    DTASDT.transaction_sequence_num ,
    DTASDT.first_snapshot_sequence_num ,
    DTASDT.commit_sequence_num ,
    DTASDT.is_snapshot ,
    DTASDT.elapsed_time_seconds ,
    DEST.text AS [command text]
    FROM sys.dm_tran_active_snapshot_database_transactions DTASDT
    INNER JOIN sys.dm_exec_connections DEC
    ON DTASDT.session_id = DEC.most_recent_session_id
    INNER JOIN sys.dm_tran_database_transactions DTDT
    ON DTASDT.transaction_id = DTDT.transaction_id
    CROSS APPLY sys.dm_exec_sql_text(DEC.most_recent_sql_handle) AS DEST
    WHERE DTDT.database_id = DB_ID()
    
    Correlating the activity of the various transactions that are using the version store
    SELECT DTTS.[transaction_sequence_num] ,
    trx_current.[session_id] AS current_session_id ,
    DES_current.[login_name] AS [current session login] ,
    DEST_current.text AS [current session command] ,
    DTTS.[snapshot_sequence_num] ,
    trx_existing.[session_id] AS existing_session_id ,
    DES_existing.[login_name] AS [existing session login] ,
    DEST_existing.text AS [existing session command]
    FROM sys.dm_tran_transactions_snapshot DTTS
    INNER JOIN sys.[dm_tran_active_snapshot_database_transactions]
    trx_current
    ON DTTS.[transaction_sequence_num] =
    trx_current.[transaction_sequence_num]
    INNER JOIN sys.[dm_exec_connections] DEC_current
    ON trx_current.[session_id] =
    DEC_current.[most_recent_session_id]
    INNER JOIN sys.[dm_exec_sessions] DES_current
    ON DEC_current.[most_recent_session_id] =
    DES_current.[session_id]
    INNER JOIN sys.[dm_tran_active_snapshot_database_transactions]
    trx_existing
    ON DTTS.[snapshot_sequence_num] =
    trx_existing.[transaction_sequence_num]
    INNER JOIN sys.[dm_exec_connections] DEC_existing
    ON trx_existing.[session_id] =
    DEC_existing.[most_recent_session_id]
    INNER JOIN sys.[dm_exec_sessions] DES_existing
    ON DEC_existing.[most_recent_session_id] =
    DES_existing.[session_id]
    CROSS APPLY sys.[dm_exec_sql_text]
    (DEC_current.[most_recent_sql_handle]) DEST_current
    CROSS APPLY sys.[dm_exec_sql_text]
    (DEC_existing.[most_recent_sql_handle]) DEST_existing
    ORDER BY DTTS.[transaction_sequence_num] ,
    DTTS.[snapshot_sequence_num] ;
    
    Returning raw data from sys.dm_tran_version_store.
    SELECT DB_NAME(DTVS.database_id) AS [Database Name] ,
    DTVS.[transaction_sequence_num] ,
    DTVS.[version_sequence_num] ,
    CASE DTVS.[status]
    WHEN 0 THEN '1'
    WHEN 1 THEN '2'
    END AS [pages] ,
    DTVS.[record_length_first_part_in_bytes]
    + DTVS.[record_length_second_part_in_bytes] AS [record length (bytes)]
    FROM sys.dm_tran_version_store DTVS
    ORDER BY DB_NAME(DTVS.database_id) ,
    DTVS.transaction_sequence_num ,
    DTVS.version_sequence_num
    
    Storage requirements for the version store
    SELECT DB_NAME(DTVS.[database_id]) ,
    SUM(DTVS.[record_length_first_part_in_bytes]
    + DTVS.[record_length_second_part_in_bytes]) AS [total store bytes
    consumed]
    FROM sys.dm_tran_version_store DTVS
    GROUP BY DB_NAME(DTVS.[database_id]) ;
    Finding the highest-consuming version store record within tempdb.
    
    WITH version_store ( [rowset_id], [bytes consumed] )
    AS ( SELECT TOP 1
    [rowset_id] ,
    SUM([record_length_first_part_in_bytes]
    + [record_length_second_part_in_bytes])
    AS [bytes consumed]
    FROM sys.dm_tran_version_store
    GROUP BY [rowset_id]
    ORDER BY SUM([record_length_first_part_in_bytes]
    + [record_length_second_part_in_bytes])
    )
    SELECT VS.[rowset_id] ,
    VS.[bytes consumed] ,
    DB_NAME(DTVS.[database_id]) AS [database name] ,
    DTASDT.[session_id] AS session_id ,
    DES.[login_name] AS [session login] ,
    DEST.text AS [session command]
    FROM version_store VS
    INNER JOIN sys.[dm_tran_version_store] DTVS
    ON VS.rowset_id = DTVS.[rowset_id]
    INNER JOIN sys.[dm_tran_active_snapshot_database_transactions]
    DTASDT
    ON DTVS.[transaction_sequence_num] =
    DTASDT.[transaction_sequence_num]
    INNER JOIN sys.dm_exec_connections DEC
    ON DTASDT.[session_id] = DEC.[most_recent_session_id]
    INNER JOIN sys.[dm_exec_sessions] DES
    ON DEC.[most_recent_session_id] = DES.[session_id]
    CROSS APPLY sys.[dm_exec_sql_text](DEC.[most_recent_sql_handle])
    DEST ;
    Returning raw data from sys.dm_tran_top_version_generators.
    SELECT DB_NAME(DTTVG.[database_id]) ,
    DTTVG.[rowset_id] ,
    DTTVG.[aggregated_record_length_in_bytes]
    FROM sys.[dm_tran_top_version_generators] DTTVG
    ORDER BY DTTVG.[aggregated_record_length_in_bytes] DESC ;
    Querying index use in the AdventureWorks database
    SELECT DB_NAME(ddius.[database_id]) AS database_name ,
    OBJECT_NAME(ddius.[object_id], DB_ID('AdventureWorks'))
    AS [object_name] ,
    asi.[name] AS index_name ,
    ddius.user_seeks + ddius.user_scans + ddius.user_lookups AS user_reads
    FROM sys.dm_db_index_usage_stats ddius
    INNER JOIN AdventureWorks.sys.indexes asi
    ON ddius.[object_id] = asi.[object_id]
    AND ddius.index_id = asi.index_id ;
    The combination of object_id and index_id cannot guarantee uniqueness at the instance level.
    SELECT DB_NAME(ddius.[database_id]) AS [database_name] ,
    ddius.[database_id] ,
    ddius.[object_id] ,
    ddius.[index_id]
    FROM sys.[dm_db_index_usage_stats] ddius
    INNER JOIN AdventureWorks.sys.[indexes] asi
    ON ddius.[object_id] = asi.[object_id]
    AND ddius.[index_id] = asi.[index_id]
    Usage stats for indexes that have been used to resolve a query.
    
    SELECT OBJECT_NAME(ddius.[object_id], ddius.database_id) AS [object_name] ,
    ddius.index_id ,
    ddius.user_seeks ,
    ddius.user_scans ,
    ddius.user_lookups ,
    ddius.user_seeks + ddius.user_scans + ddius.user_lookups
    AS user_reads ,
    ddius.user_updates AS user_writes ,
    ddius.last_user_scan ,
    ddius.last_user_update
    FROM sys.dm_db_index_usage_stats ddius
    WHERE ddius.database_id > 4 -- filter out system tables
    AND OBJECTPROPERTY(ddius.object_id, 'IsUserTable') = 1
    AND ddius.index_id > 0 -- filter out heaps
    ORDER BY ddius.user_scans DESC
    Finding unused indexes.
    -- List unused indexes
    SELECT OBJECT_NAME(i.[object_id]) AS [Table Name] ,
    i.name
    FROM sys.indexes AS i
    INNER JOIN sys.objects AS o ON i.[object_id] = o.[object_id]
    WHERE i.index_id NOT IN ( SELECT ddius.index_id
    FROM sys.dm_db_index_usage_stats AS ddius
    WHERE ddius.[object_id] = i.[object_id]
    AND i.index_id = ddius.index_id AND database_id = DB_ID() )
    AND o.[type] = 'U'
    ORDER BY OBJECT_NAME(i.[object_id]) ASC ;
    Querying sys.dm_db_index_usage_stats for indexes that are being maintained but not used.
    
    SELECT '[' + DB_NAME() + '].[' + su.[name] + '].[' + o.[name] + ']'
    AS [statement] ,
    i.[name] AS [index_name] ,
    ddius.[user_seeks] + ddius.[user_scans] + ddius.[user_lookups]
    AS [user_reads] ,
    ddius.[user_updates] AS [user_writes] ,
    SUM(SP.rows) AS [total_rows]
    FROM sys.dm_db_index_usage_stats ddius
    INNER JOIN sys.indexes i ON ddius.[object_id] = i.[object_id]
    AND i.[index_id] = ddius.[index_id]
    INNER JOIN sys.partitions SP ON ddius.[object_id] = SP.[object_id]
    AND SP.[index_id] = ddius.[index_id]
    INNER JOIN sys.objects o ON ddius.[object_id] = o.[object_id]
    INNER JOIN sys.sysusers su ON o.[schema_id] = su.[UID]
    WHERE ddius.[database_id] = DB_ID() -- current database only
    AND OBJECTPROPERTY(ddius.[object_id], 'IsUserTable') = 1
    AND ddius.[index_id] > 0
    GROUP BY su.[name] ,
    o.[name] ,
    i.[name] ,
    ddius.[user_seeks] + ddius.[user_scans] + ddius.[user_lookups] ,
    ddius.[user_updates]
    HAVING ddius.[user_seeks] + ddius.[user_scans] + ddius.[user_lookups] = 0
    ORDER BY ddius.[user_updates] DESC ,
    su.[name] ,
    o.[name] ,
    i.[name ]
    Genarage drop index command in SELECT
    
    'DROP INDEX [' + i.[name] + '] ON [' + su.[name] + '].[' + o.[name]
    + '] WITH ( ONLINE = OFF )' AS [drop_command]
    
    How old are the index usage stats?
    SELECT DATEDIFF(DAY, sd.crdate, GETDATE()) AS days_history
    FROM sys.sysdatabases sd
    WHERE sd.[name] = 'tempdb' ;
    Finding rarely-used indexes.
    
    -- Potentially inefficient non-clustered indexes (writes > reads)
    SELECT OBJECT_NAME(ddius.[object_id]) AS [Table Name] ,
    i.name AS [Index Name] ,
    i.index_id ,
    user_updates AS [Total Writes] ,
    user_seeks + user_scans + user_lookups AS [Total Reads] ,
    user_updates - ( user_seeks + user_scans + user_lookups )
    AS [Difference]
    FROM sys.dm_db_index_usage_stats AS ddius WITH ( NOLOCK )
    INNER JOIN sys.indexes AS i WITH ( NOLOCK )
    ON ddius.[object_id] = i.[object_id]
    AND i.index_id = ddius.index_id
    WHERE OBJECTPROPERTY(ddius.[object_id], 'IsUserTable') = 1
    AND ddius.database_id = DB_ID()
    AND user_updates > ( user_seeks + user_scans + user_lookups )
    AND i.index_id > 1
    ORDER BY [Difference] DESC ,
    [Total Writes] DESC ,
    [Total Reads] ASC ;
    Detailed write information for unused indexes.
    
    SELECT '[' + DB_NAME() + '].[' + su.[name] + '].[' + o.[name] + ']'
    AS [statement] ,
    i.[name] AS [index_name] ,
    ddius.[user_seeks] + ddius.[user_scans] + ddius.[user_lookups]
    AS [user_reads] ,
    ddius.[user_updates] AS [user_writes] ,
    ddios.[leaf_insert_count] ,
    ddios.[leaf_delete_count] ,
    ddios.[leaf_update_count] ,
    ddios.[nonleaf_insert_count] ,
    ddios.[nonleaf_delete_count] ,
    ddios.[nonleaf_update_count]
    FROM sys.dm_db_index_usage_stats ddius
    INNER JOIN sys.indexes i ON ddius.[object_id] = i.[object_id]
    AND i.[index_id] = ddius.[index_id]
    INNER JOIN sys.partitions SP ON ddius.[object_id] = SP.[object_id]
    AND SP.[index_id] = ddius.[index_id]
    INNER JOIN sys.objects o ON ddius.[object_id] = o.[object_id]
    INNER JOIN sys.sysusers su ON o.[schema_id] = su.[UID]
    INNER JOIN sys.[dm_db_index_operational_stats](DB_ID(), NULL, NULL,
    NULL)
    AS ddios
    ON ddius.[index_id] = ddios.[index_id] 
    AND ddius.[object_id] = ddios.[object_id]
    AND SP.[partition_number] = ddios.[partition_number]
    AND ddius.[database_id] = ddios.[database_id]
    WHERE OBJECTPROPERTY(ddius.[object_id], 'IsUserTable') = 1
    AND ddius.[index_id] > 0
    AND ddius.[user_seeks] + ddius.[user_scans] + ddius.[user_lookups] = 0
    ORDER BY ddius.[user_updates] DESC ,
    su.[name] ,
    o.[name] ,
    i.[name ]
    Retrieving locking and blocking details for each index.
    
    SELECT '[' + DB_NAME(ddios.[database_id]) + '].[' + su.[name] + '].['
    + o.[name] + ']' AS [statement] ,
    i.[name] AS 'index_name' ,
    ddios.[partition_number] ,
    ddios.[row_lock_count] ,
    ddios.[row_lock_wait_count] ,
    CAST (100.0 * ddios.[row_lock_wait_count]
    / ( ddios.[row_lock_count] ) AS DECIMAL(5, 2)) AS [%_times_blocked] ,
    ddios.[row_lock_wait_in_ms] ,
    CAST (1.0 * ddios.[row_lock_wait_in_ms]
    / ddios.[row_lock_wait_count] AS DECIMAL(15, 2))
    AS [avg_row_lock_wait_in_ms]
    FROM sys.dm_db_index_operational_stats(DB_ID(), NULL, NULL, NULL) ddios
    INNER JOIN sys.indexes i ON ddios.[object_id] = i.[object_id]
    AND i.[index_id] = ddios.[index_id]
    INNER JOIN sys.objects o ON ddios.[object_id] = o.[object_id]
    INNER JOIN sys.sysusers su ON o.[schema_id] = su.[UID]
    WHERE ddios.row_lock_wait_count > 0
    AND OBJECTPROPERTY(ddios.[object_id], 'IsUserTable') = 1
    AND i.[index_id] > 0
    ORDER BY ddios.[row_lock_wait_count] DESC ,
    su.[name] ,
    o.[name] ,
    i.[name ]
    Investigating latch waits.
    SELECT '[' + DB_NAME() + '].[' + OBJECT_SCHEMA_NAME(ddios.[object_id])
    + '].[' + OBJECT_NAME(ddios.[object_id]) + ']' AS [object_name] ,
    i.[name] AS index_name ,
    ddios.page_io_latch_wait_count ,
    ddios.page_io_latch_wait_in_ms ,
    ( ddios.page_io_latch_wait_in_ms / ddios.page_io_latch_wait_count )
    AS avg_page_io_latch_wait_in_ms
    FROM sys.dm_db_index_operational_stats(DB_ID(), NULL, NULL, NULL) ddios
    INNER JOIN sys.indexes i ON ddios.[object_id] = i.[object_id]
    AND i.index_id = ddios.index_id
    WHERE ddios.page_io_latch_wait_count > 0
    AND OBJECTPROPERTY(i.object_id, 'IsUserTable') = 1
    ORDER BY ddios.page_io_latch_wait_count DESC ,
    avg_page_io_latch_wait_in_ms DESC
    Investigating lock escalation.
    
    SELECT OBJECT_NAME(ddios.[object_id], ddios.database_id) AS [object_name] ,
    i.name AS index_name ,
    ddios.index_id ,
    ddios.partition_number ,
    ddios.index_lock_promotion_attempt_count ,
    ddios.index_lock_promotion_count ,
    ( ddios.index_lock_promotion_attempt_count
    / ddios.index_lock_promotion_count ) AS percent_success
    FROM sys.dm_db_index_operational_stats(DB_ID(), NULL, NULL, NULL) ddios
    INNER JOIN sys.indexes i ON ddios.object_id = i.object_id
    AND ddios.index_id = i.index_id
    WHERE ddios.index_lock_promotion_count > 0
    ORDER BY index_lock_promotion_count DESC ;
    Indexes associated with lock contention.
    SELECT OBJECT_NAME(ddios.object_id, ddios.database_id) AS object_name ,
    i.name AS index_name ,
    ddios.index_id ,
    ddios.partition_number ,
    ddios.page_lock_wait_count ,
    ddios.page_lock_wait_in_ms ,
    CASE WHEN DDMID.database_id IS NULL THEN 'N'
    ELSE 'Y'
    END AS missing_index_identified
    FROM sys.dm_db_index_operational_stats(DB_ID(), NULL, NULL, NULL) ddios
    INNER JOIN sys.indexes i ON ddios.object_id = i.object_id
    AND ddios.index_id = i.index_id
    LEFT OUTER JOIN ( SELECT DISTINCT
    database_id ,
    object_id
    FROM sys.dm_db_missing_index_details
    ) AS DDMID ON DDMID.database_id = ddios.database_id
    AND DDMID.object_id = ddios.object_id
    WHERE ddios.page_lock_wait_in_ms > 0
    ORDER BY ddios.page_lock_wait_count DESC ;
    Finding beneficial missing indexes.
    SELECT user_seeks * avg_total_user_cost * ( avg_user_impact * 0.01 )
    AS [index_advantage] ,
    dbmigs.last_user_seek ,
    dbmid.[statement] AS [Database.Schema.Table] ,
    dbmid.equality_columns ,
    dbmid.inequality_columns ,
    dbmid.included_columns ,
    dbmigs.unique_compiles ,
    dbmigs.user_seeks ,
    dbmigs.avg_total_user_cost ,
    dbmigs.avg_user_impact
    FROM sys.dm_db_missing_index_group_stats AS dbmigs WITH ( NOLOCK )
    INNER JOIN sys.dm_db_missing_index_groups AS dbmig WITH ( NOLOCK )
    ON dbmigs.group_handle = dbmig.index_group_handle
    INNER JOIN sys.dm_db_missing_index_details AS dbmid WITH ( NOLOCK )
    ON dbmig.index_handle = dbmid.index_handle
    WHERE dbmid.[database_id] = DB_ID()
    ORDER BY index_advantage DESC ;
    Investigating fragmented indexes.
    
    SELECT '[' + DB_NAME() + '].[' + OBJECT_SCHEMA_NAME(ddips.[object_id],
    DB_ID()) + '].['
    + OBJECT_NAME(ddips.[object_id], DB_ID()) + ']' AS [statement] ,
    i.[name] AS [index_name] ,
    ddips.[index_type_desc] ,
    ddips.[partition_number] ,
    ddips.[alloc_unit_type_desc] ,
    ddips.[index_depth] ,
    ddips.[index_level] ,
    CAST(ddips.[avg_fragmentation_in_percent] AS SMALLINT)
    AS [avg_frag_%] ,
    CAST(ddips.[avg_fragment_size_in_pages] AS SMALLINT)
    AS [avg_frag_size_in_pages] ,
    ddips.[fragment_count] ,
    ddips.[page_count]
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL,
    NULL, NULL, 'limited') ddips
    INNER JOIN sys.[indexes] i ON ddips.[object_id] = i.[object_id]
    AND ddips.[index_id] = i.[index_id]
    WHERE ddips.[avg_fragmentation_in_percent] > 15
    AND ddips.[page_count] > 500
    ORDER BY ddips.[avg_fragmentation_in_percent] ,
    OBJECT_NAME(ddips.[object_id], DB_ID()) ,
    i.[name ]
    Number of rows in clustered tables and heaps.
    
    SELECT object_schema_name(ddps.object_id) +
    '.' + OBJECT_NAME(ddps.object_id) AS name ,
    SUM(ddps.row_count) AS row_count
    FROM sys.dm_db_partition_stats AS ddps
    JOIN sys.indexes ON indexes.object_id = ddps.object_id
    AND indexes.index_id = ddps.index_id
    WHERE indexes.type_desc IN ( 'CLUSTERED', 'HEAP' )
    and objectproperty(ddps.object_id,'IsMSShipped') = 0
    GROUP BY ddps.object_id
    Creating a three-partition salesOrder table.
    
    CREATE PARTITION FUNCTION PFdateRange (SMALLDATETIME)
    AS RANGE LEFT FOR VALUES ('20020101','20030101') ;
    GO
    CREATE PARTITION SCHEME PSdateRange
    AS PARTITION PFdateRange ALL TO ( [PRIMARY] )
    GO
    CREATE TABLE salesOrder
    (
    salesOrderId INT ,
    customerId INT ,
    orderAmount DECIMAL(10, 2) ,
    orderDate SMALLDATETIME ,
    CONSTRAINT PKsalesOrder PRIMARY KEY NONCLUSTERED ( salesOrderId )
    ON [Primary] ,
    CONSTRAINT AKsalesOrder UNIQUE CLUSTERED ( salesOrderId, orderDate )
    )
    --the ON clause causes this clustered table to be partitioned by orderDate
    --using the partition function/scheme
    ON PSdateRange(orderDate)
    GO
    --Generate some random data
    INSERT INTO salesOrder
    SELECT SalesOrderId ,
    CustomerId ,
    TotalDue ,
    OrderDate
    FROM AdventureWorks.Sales.SalesOrderHeader
    Number of rows in each object, per partition.
    SELECT indexes.name ,
    indexes.type_desc ,
    dps.row_count AS row_count ,
    partition_id
    FROM sys.dm_db_partition_stats AS dps
    JOIN sys.indexes ON indexes.object_id = dps.object_id
    AND indexes.index_id = dps.index_id
    WHERE OBJECT_ID('salesOrder') = dps.object_id
    Physical characteristics of each partition
    
    SELECT OBJECT_NAME(indexes.object_id) AS Object_Name ,
    ddps.index_id AS Index_ID ,
    ddps.partition_number ,
    ddps.row_count ,
    ddps.used_page_count ,
    ddps.in_row_reserved_page_count ,
    ddps.lob_reserved_page_count ,
    CASE pf.boundary_value_on_right
    WHEN 1 THEN 'less than'
    ELSE 'less than or equal to'
    END AS comparison ,
    value
    FROM sys.dm_db_partition_stats ddps
    JOIN sys.indexes ON ddps.object_id = indexes.object_id
    AND ddps.index_id = indexes.index_id
    JOIN sys.partition_schemes ps
    ON ps.data_space_id = indexes.data_space_id
    JOIN sys.partition_functions pf ON pf.function_id = ps.function_id
    LEFT OUTER JOIN sys.partition_range_values prv
    ON pf.function_id = prv.function_id
    AND ddps.partition_number = prv.boundary_id
    WHERE OBJECT_NAME(ddps.object_id) = 'salesOrder '
    AND ddps.index_id IN ( 0, 1 ) --CLUSTERED table or HEAP
    Fragmentation statistics for the testClusteredIdentity clustered table
    SELECT avg_fragmentation_in_percent AS avgFragPct ,
    fragment_count AS fragCount ,
    avg_fragment_size_in_pages AS avgFragSize
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED')
    WHERE index_type_desc = 'CLUSTERED INDEX'
    AND index_level = 0 -- the other levels are the index pages
    AND OBJECT_NAME(object_id) = 'testClusteredIdentity'
    Fragmentation statistics for testHeap.
    
    SELECT avg_fragmentation_in_percent AS avgFragPct ,
    fragment_count AS fragCount ,
    avg_fragment_size_in_pages AS avgFragSize ,
    forwarded_record_count AS forwardPointers
    FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED')
    WHERE index_type_desc = 'HEAP'
    AND index_level = 0 -- the other levels are the index pages
    AND OBJECT_NAME(object_id) = 'testHeap'
    Capturing baseline disk I/O statistics from sys.dm_io_virtual_file_stats in a temporary table.
    
    SELECT DB_NAME(mf.database_id) AS databaseName ,
    mf.physical_name ,
    divfs.num_of_reads ,
    divfs.num_of_bytes_read ,
    divfs.io_stall_read_ms ,
    divfs.num_of_writes ,
    divfs.num_of_bytes_written ,
    divfs.io_stall_write_ms ,
    divfs.io_stall ,
    size_on_disk_bytes ,
    GETDATE() AS baselineDate
    INTO #baseline
    FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    JOIN sys.master_files AS mf ON mf.database_id = divfs.database_id
    AND mf.file_id = divfs.file_id
    Querying the #baseline temporary table.
    SELECT physical_name ,
    num_of_reads ,
    num_of_bytes_read ,
    io_stall_read_ms
    FROM #baseline
    WHERE databaseName = 'DatabaseName'
    Capturing 10 seconds of disk I/O statistics, since the baseline measurement.
    
    WITH currentLine
    AS ( SELECT DB_NAME(mf.database_id) AS databaseName ,
    mf.physical_name ,
    num_of_reads ,
    num_of_bytes_read ,
    io_stall_read_ms ,
    num_of_writes ,
    num_of_bytes_written ,
    io_stall_write_ms ,
    io_stall ,
    size_on_disk_bytes ,
    GETDATE() AS currentlineDate
    FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    JOIN sys.master_files AS mf
    ON mf.database_id = divfs.database_id
    AND mf.file_id = divfs.file_id
    )
    SELECT currentLine.databaseName ,
    LEFT(currentLine.physical_name, 1) AS drive ,
    currentLine.physical_name ,
    DATEDIFF(millisecond,baseLineDate,currentLineDate) AS elapsed_ms,
    currentLine.io_stall - #baseline.io_stall AS io_stall_ms ,
    currentLine.io_stall_read_ms - #baseline.io_stall_read_ms
    AS io_stall_read_ms ,
    currentLine.io_stall_write_ms - #baseline.io_stall_write_ms
    AS io_stall_write_ms ,
    currentLine.num_of_reads - #baseline.num_of_reads AS num_of_reads ,
    currentLine.num_of_bytes_read - #baseline.num_of_bytes_read
    AS num_of_bytes_read ,
    currentLine.num_of_writes - #baseline.num_of_writes AS num_of_writes ,
    currentLine.num_of_bytes_written - #baseline.num_of_bytes_written
    AS num_of_bytes_written
    FROM currentLine
    INNER JOIN #baseline ON #baseLine.databaseName = currentLine.databaseName
    AND #baseLine.physical_name = currentLine.physical_name
    WHERE #baseline.databaseName = 'DatabaseName'
    Returning pending I/O requests.
    
    SELECT mf.physical_name ,
    dipir.io_pending ,
    dipir.io_pending_ms_ticks
    FROM sys.dm_io_pending_io_requests AS dipir
    JOIN sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    ON dipir.io_handle = divfs.file_handle
    JOIN sys.master_files AS mf ON divfs.database_id = mf.database_id
    AND divfs.file_id = mf.file_id
    ORDER BY dipir.io_pending , --Show I/O completed by the OS first
    dipir.io_pending_ms_ticks DESC
    The read:write ratio, by database, for amount of data transferred.
    
    --uses a LIKE comparison to only include desired databases, rather than
    --using the database_id parameter of sys.dm_io_virtual_file_stats
    --if you have a rather large number of databases, this may not be the
    --optimal way to execute the query, but this gives you flexibility
    --to look at multiple databases simultaneously.
    DECLARE @databaseName SYSNAME
    SET @databaseName = '%'
    --'%' gives all databases
    SELECT CAST(SUM(num_of_bytes_read) AS DECIMAL)
    / ( CAST(SUM(num_of_bytes_written) AS DECIMAL)
    + CAST(SUM(num_of_bytes_read) AS DECIMAL) ) AS RatioOfReads ,
    CAST(SUM(num_of_bytes_written) AS DECIMAL)
    / ( CAST(SUM(num_of_bytes_written) AS DECIMAL)
    + CAST(SUM(num_of_bytes_read) AS DECIMAL) ) AS RatioOfWrites ,
    SUM(num_of_bytes_read) AS TotalBytesRead ,
    SUM(num_of_bytes_written) AS TotalBytesWritten
    FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    WHERE DB_NAME(database_id) LIKE @databaseName
    The read:write ratio, by drive, for amount of data transferred.
    
    DECLARE @databaseName SYSNAME
    SET @databaseName = '%'
    --'%' gives all databases
    SELECT LEFT(physical_name, 1) AS drive ,
    CAST(SUM(num_of_bytes_read) AS DECIMAL)
    / ( CAST(SUM(num_of_bytes_written) AS DECIMAL)
    + CAST(SUM(num_of_bytes_read) AS DECIMAL) ) AS RatioOfReads ,
    CAST(SUM(num_of_bytes_written) AS DECIMAL)
    / ( CAST(SUM(num_of_bytes_written) AS DECIMAL)
    + CAST(SUM(num_of_bytes_read) AS DECIMAL) ) AS RatioOfWrites ,
    SUM(num_of_bytes_read) AS TotalBytesRead ,
    SUM(num_of_bytes_written) AS TotalBytesWritten
    FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    JOIN sys.master_files AS mf ON mf.database_id = divfs.database_id
    AND mf.file_id = divfs.file_id
    WHERE DB_NAME(divfs.database_id) LIKE @databaseName
    GROUP BY LEFT(mf.physical_name, 1)
    The read:write ratio, by database, for number of read/write operations.
    
    DECLARE @databaseName SYSNAME
    SET @databaseName = 'BusyDatabase'
    --obviously not the real name
    --'%' gives all databases
    SELECT CAST(SUM(num_of_reads) AS DECIMAL)
    / ( CAST(SUM(num_of_writes) AS DECIMAL)
    + CAST(SUM(num_of_reads) AS DECIMAL) ) AS RatioOfReads ,
    CAST(SUM(num_of_writes) AS DECIMAL)
    / ( CAST(SUM(num_of_reads) AS DECIMAL)
    + CAST(SUM(num_of_writes) AS DECIMAL) ) AS RatioOfWrites ,
    SUM(num_of_reads) AS TotalReadOperations ,
    SUM(num_of_writes) AS TotalWriteOperations
    FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS divfs
    WHERE DB_NAME(database_id) LIKE @databaseName
    Read:write ratio for all objects in a given database.
    
    DECLARE @databaseName SYSNAME
    SET @databaseName = 'BusyDatabase' --obviously not the real name
    --'%' gives all databases
    SELECT CASE
    WHEN ( SUM(user_updates + user_seeks + user_scans + user_lookups) = 0 )
    THEN NULL
    ELSE ( CAST(SUM(user_seeks + user_scans + user_lookups)
    AS DECIMAL)
    / CAST(SUM(user_updates + user_seeks + user_scans
    + user_lookups) AS DECIMAL) )
    END AS RatioOfReads ,
    CASE
    WHEN ( SUM(user_updates + user_seeks + user_scans + user_lookups) = 0 )
    THEN NULL
    ELSE ( CAST(SUM(user_updates) AS DECIMAL)
    / CAST(SUM(user_updates + user_seeks + user_scans
    + user_lookups) AS DECIMAL) )
    END AS RatioOfWrites ,
    SUM(user_updates + user_seeks + user_scans + user_lookups)
    AS TotalReadOperations ,
    SUM(user_updates) AS TotalWriteOperations
    FROM sys.dm_db_index_usage_stats AS ddius
    WHERE DB_NAME(database_id) LIKE @databaseName
    Read:write ratio per object.
    
    --only works in the context of the database due to sys.indexes usage
    USE BusyDatabase
    --obviously not the real name
    SELECT OBJECT_NAME(ddius.object_id) AS object_name ,
    CASE
    WHEN ( SUM(user_updates + user_seeks + user_scans + user_lookups) = 0 )
    THEN NULL
    ELSE ( CAST(SUM(user_seeks + user_scans + user_lookups) AS DECIMAL)
    / CAST(SUM(user_updates + user_seeks + user_scans
    + user_lookups) AS DECIMAL) )
    END AS RatioOfReads ,
    CASE
    WHEN ( SUM(user_updates + user_seeks + user_scans + user_lookups) = 0 )
    THEN NULL
    ELSE ( CAST(SUM(user_updates) AS DECIMAL)
    / CAST(SUM(user_updates + user_seeks + user_scans
    + user_lookups) AS DECIMAL) )
    END AS RatioOfWrites ,
    SUM(user_updates + user_seeks + user_scans + user_lookups)
    AS TotalReadOperations ,
    SUM(user_updates) AS TotalWriteOperations
    FROM sys.dm_db_index_usage_stats AS ddius
    JOIN sys.indexes AS i ON ddius.object_id = i.object_id
    AND ddius.index_id = i.index_id
    WHERE i.type_desc IN ( 'CLUSTERED', 'HEAP' ) --only works in Current db
    GROUP BY ddius.object_id
    ORDER BY OBJECT_NAME(ddius.object_id)
    An overview of tempdb utilization.
    
    SELECT mf.physical_name ,
    mf.size AS entire_file_page_count ,
    dfsu.version_store_reserved_page_count ,
    dfsu.unallocated_extent_page_count ,
    dfsu.user_object_reserved_page_count ,
    dfsu.internal_object_reserved_page_count ,
    dfsu.mixed_extent_page_count
    FROM sys.dm_db_file_space_usage dfsu
    JOIN sys.master_files AS mf ON mf.database_id = dfsu.database_id
    AND mf.file_id = dfsu.file_id
    tempdb file size and version store usage.
    
    SELECT SUM(mf.size) AS entire_page_count ,
    SUM(dfsu.version_store_reserved_page_count) AS version_store_reserved_page_
    count
    FROM sys.dm_db_file_space_usage dfsu
    JOIN sys.master_files AS mf ON mf.database_id = dfsu.database_id
    AND mf.file_id = dfsu.file_id
    Resetting the wait statistics.
    DBCC SQLPERF ('sys.dm_os_wait_stats', CLEAR);
    The most common waits.
    
    SELECT TOP 3
    wait_type ,
    waiting_tasks_count ,
    wait_time_ms / 1000.0 AS wait_time_sec ,
    CASE WHEN waiting_tasks_count = 0 THEN NULL
    ELSE wait_time_ms / 1000.0 / waiting_tasks_count
    END AS avg_wait_time_sec ,
    max_wait_time_ms / 1000.0 AS max_wait_time_sec ,
    ( wait_time_ms - signal_wait_time_ms ) / 1000.0 AS resource_wait_time_sec
    FROM sys.dm_os_wait_stats
    WHERE wait_type NOT IN --tasks that are actually good or expected
    --to be waited on
    ( 'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
    'SLEEP_SYSTEMTASK', 'WAITFOR' )
    ORDER BY waiting_tasks_count DESC
    Report on top resource waits.
    
    -- Isolate top waits for server instance since last restart
    -- or statistics clear
    WITH Waits
    AS ( SELECT wait_type ,
    wait_time_ms / 1000. AS wait_time_sec ,
    100. * wait_time_ms / SUM(wait_time_ms) OVER ( ) AS pct ,
    ROW_NUMBER() OVER ( ORDER BY wait_time_ms DESC ) AS rn
    FROM sys.dm_os_wait_stats
    WHERE wait_type NOT IN ( 'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP',
    'RESOURCE_QUEUE', 'SLEEP_TASK',
    'SLEEP_SYSTEMTASK',
    'SQLTRACE_BUFFER_FLUSH', 'WAITFOR',
    'LOGMGR_QUEUE', 'CHECKPOINT_QUEUE' )
    )
    SELECT wait_type ,
    CAST(wait_time_sec AS DECIMAL(12, 2)) AS wait_time_sec ,
    CAST(pct AS DECIMAL(12, 2)) AS wait_time_percentage
    FROM Waits
    WHERE pct > 1
    ORDER BY wait_time_sec DESC
    Seeking out locking waits.
    
    SELECT wait_type ,
    waiting_tasks_count ,
    wait_time_ms ,
    max_wait_time_ms
    FROM sys.dm_os_wait_stats
    WHERE wait_type LIKE 'LCK%'
    AND Waiting_tasks_count > 0
    ORDER BY waiting_tasks_count DESC
    Is there any CPU pressure?
    
    -- Total waits are wait_time_ms (high signal waits indicates CPU pressure)
    SELECT CAST(100.0 * SUM(signal_wait_time_ms) / SUM(wait_time_ms)
    AS NUMERIC(20,2)) AS [%signal (cpu) waits] ,
    CAST(100.0 * SUM(wait_time_ms - signal_wait_time_ms)
    / SUM(wait_time_ms) AS NUMERIC(20, 2)) AS [%resource waits]
    FROM sys.dm_os_wait_stats ;
    Returning a list of PerfMon counter types.
    
    SELECT DISTINCT
    cntr_type
    FROM sys.dm_os_performance_counters
    ORDER BY cntr_type
    Returning the values of directly usable PerfMon counters.
    
    DECLARE @PERF_COUNTER_LARGE_RAWCOUNT INT
    SELECT @PERF_COUNTER_LARGE_RAWCOUNT = 65792
    SELECT object_name ,
    counter_name ,
    instance_name ,
    cntr_value
    FROM sys.dm_os_performance_counters
    WHERE cntr_type = @PERF_COUNTER_LARGE_RAWCOUNT
    ORDER BY object_name ,
    counter_name ,
    instance_name
    Monitoring changes in the size of the transaction log.
    
    --the default instance reports as SQLServer, but other
    --instances as MSSQL$InstanceName
    DECLARE @object_name SYSNAME
    SET @object_name = CASE WHEN @@servicename = 'MSSQLSERVER' THEN 'SQLServer'
    ELSE 'MSSQL$' + @@serviceName
    END + ':Databases'
    DECLARE @PERF_COUNTER_LARGE_RAWCOUNT INT
    SELECT @PERF_COUNTER_LARGE_RAWCOUNT = 65792
    SELECT object_name ,
    counter_name ,
    instance_name ,
    cntr_value
    FROM sys.dm_os_performance_counters
    WHERE cntr_type = @PERF_COUNTER_LARGE_RAWCOUNT
    AND object_name = @object_name
    AND counter_name IN ( 'Log Growths', 'Log Shrinks' )
    AND cntr_value > 0
    ORDER BY object_name ,
    counter_name ,
    instance_name
    Which deprecated features are still in use?
    DECLARE @object_name SYSNAME
    SET @object_name = CASE WHEN @@servicename = 'MSSQLSERVER' THEN 'SQLServer'
    ELSE 'MSSQL$' + @@serviceName
    END + ':Deprecated Features'
    DECLARE @PERF_COUNTER_LARGE_RAWCOUNT INT
    SELECT @PERF_COUNTER_LARGE_RAWCOUNT = 65792
    SELECT object_name ,
    counter_name ,
    instance_name ,
    cntr_value
    FROM sys.dm_os_performance_counters
    WHERE cntr_type = @PERF_COUNTER_LARGE_RAWCOUNT
    AND object_name = @object_name
    AND cntr_value > 0
    Returning the values of ratio PerfMon counters.
    
    DECLARE @PERF_LARGE_RAW_FRACTION INT ,
    @PERF_LARGE_RAW_BASE INT
    SELECT @PERF_LARGE_RAW_FRACTION = 537003264 ,
    @PERF_LARGE_RAW_BASE = 1073939712
    SELECT dopc_fraction.object_name ,
    dopc_fraction.instance_name ,
    dopc_fraction.counter_name ,
    --when divisor is 0, return I return NULL to indicate
    --divide by 0/no values captured
    CAST(dopc_fraction.cntr_value AS FLOAT)
    / CAST(CASE dopc_base.cntr_value
    WHEN 0 THEN NULL
    ELSE dopc_base.cntr_value
    END AS FLOAT) AS cntr_value
    FROM sys.dm_os_performance_counters AS dopc_base
    JOIN sys.dm_os_performance_counters AS dopc_fraction
    ON dopc_base.cntr_type = @PERF_LARGE_RAW_BASE
    AND dopc_fraction.cntr_type = @PERF_LARGE_RAW_FRACTION
    AND dopc_base.object_name = dopc_fraction.object_name
    AND dopc_base.instance_name = dopc_fraction.instance_name
    AND ( REPLACE(dopc_base.counter_name,
    'base', '') = dopc_fraction.counter_name
    --Worktables From Cache has "odd" name where
    --Ratio was left off
    OR REPLACE(dopc_base.counter_name,
    'base', '') = ( REPLACE(dopc_fraction.counter_name,
    'ratio', '') )
    )
    ORDER BY dopc_fraction.object_name ,
    dopc_fraction.instance_name ,
    dopc_fraction.counter_name
    Returning the current value for the buffer cache hit ratio.
    
    DECLARE @object_name SYSNAME
    SET @object_name = CASE WHEN @@servicename = 'MSSQLSERVER' THEN 'SQLServer'
    ELSE 'MSSQL$' + @@serviceName
    END + ':Buffer Manager'
    DECLARE
    @PERF_LARGE_RAW_FRACTION INT ,
    @PERF_LARGE_RAW_BASE INT
    SELECT @PERF_LARGE_RAW_FRACTION = 537003264 ,
    @PERF_LARGE_RAW_BASE = 1073939712
    SELECT dopc_fraction.object_name ,
    dopc_fraction.instance_name ,
    dopc_fraction.counter_name ,
    --when divisor is 0, return I return NULL to indicate
    --divide by 0/no values captured
    CAST(dopc_fraction.cntr_value AS FLOAT)
    / CAST(CASE dopc_base.cntr_value
    WHEN 0 THEN NULL
    ELSE dopc_base.cntr_value
    END AS FLOAT) AS cntr_value
    FROM sys.dm_os_performance_counters AS dopc_base
    JOIN sys.dm_os_performance_counters AS dopc_fraction
    ON dopc_base.cntr_type = @PERF_LARGE_RAW_BASE
    AND dopc_fraction.cntr_type = @PERF_LARGE_RAW_FRACTION
    AND dopc_base.object_name = dopc_fraction.object_name
    AND dopc_base.instance_name = dopc_fraction.instance_name
    AND ( REPLACE(dopc_base.counter_name,
    'base', '') = dopc_fraction.counter_name
    --Worktables From Cache has "odd" name where
    --Ratio was left off
    OR REPLACE(dopc_base.counter_name,
    'base', '') = ( REPLACE(dopc_fraction.counter_name,
    'ratio', '') )
    )
    WHERE dopc_fraction.object_name = @object_name
    AND dopc_fraction.instance_name = ''
    AND dopc_fraction.counter_name = 'Buffer cache hit ratio'
    ORDER BY dopc_fraction.object_name ,
    dopc_fraction.instance_name ,
    dopc_fraction.counter_name
    
    Returning the values of "per second average" PerfMon counters.
    
    DECLARE @PERF_COUNTER_BULK_COUNT INT
    SELECT @PERF_COUNTER_BULK_COUNT = 272696576
    --Holds initial state
    DECLARE @baseline TABLE
    (
    object_name NVARCHAR(256) ,
    counter_name NVARCHAR(256) ,
    instance_name NVARCHAR(256) ,
    cntr_value BIGINT ,
    cntr_type INT ,
    time DATETIME DEFAULT ( GETDATE() )
    )
    DECLARE @current TABLE
    (
    object_name NVARCHAR(256) ,
    counter_name NVARCHAR(256) ,
    instance_name NVARCHAR(256) ,
    cntr_value BIGINT ,
    cntr_type INT ,
    time DATETIME DEFAULT ( GETDATE() )
    )
    --capture the initial state of bulk counters
    INSERT INTO @baseline
    ( object_name ,
    counter_name ,
    instance_name ,
    cntr_value ,
    cntr_type
    )
    SELECT object_name ,
    counter_name ,
    instance_name ,
    cntr_value ,
    cntr_type
    FROM sys.dm_os_performance_counters AS dopc
    WHERE cntr_type = @PERF_COUNTER_BULK_COUNT
    WAITFOR DELAY '00:00:05' --the code will work regardless of delay chosen
    --get the followon state of the counters
    INSERT INTO @current
    ( object_name ,
    counter_name ,
    instance_name ,
    cntr_value ,
    cntr_type
    )
    SELECT object_name ,
    counter_name ,
    instance_name ,
    cntr_value ,
    cntr_type
    FROM sys.dm_os_performance_counters AS dopc
    WHERE cntr_type = @PERF_COUNTER_BULK_COUNT
    SELECT dopc.object_name ,
    dopc.instance_name ,
    dopc.counter_name ,
    --ms to second conversion factor
    1000 *
    --current value less the previous value
    ( ( dopc.cntr_value - prev_dopc.cntr_value )
    --divided by the number of milliseconds that pass
    --casted as float to get fractional results. Float
    --lets really big or really small numbers to work
    / CAST(DATEDIFF(ms, prev_dopc.time, dopc.time) AS FLOAT) )
    AS cntr_value
    --simply join on the names of the counters
    FROM @current AS dopc
    JOIN @baseline AS prev_dopc ON prev_dopc.object_name = dopc.object_name
    AND prev_dopc.instance_name = dopc.instance_name
    AND prev_dopc.counter_name = dopc.counter_name
    WHERE dopc.cntr_type = @PERF_COUNTER_BULK_COUNT
    AND 1000 * ( ( dopc.cntr_value - prev_dopc.cntr_value )
    / CAST(DATEDIFF(ms, prev_dopc.time, dopc.time) AS FLOAT) )
    /* default to only showing non-zero values */ <> 0
    ORDER BY dopc.object_name ,
    dopc.instance_name ,
    dopc.counter_name
    
    Returning the values for the "average number of operations" PerfMon counters.
    
    DECLARE @PERF_AVERAGE_BULK INT ,
    @PERF_LARGE_RAW_BASE INT
    SELECT @PERF_AVERAGE_BULK = 1073874176 ,
    @PERF_LARGE_RAW_BASE = 1073939712
    SELECT dopc_avgBulk.object_name ,
    dopc_avgBulk.instance_name ,
    dopc_avgBulk.counter_name ,
    CAST(dopc_avgBulk.cntr_value AS FLOAT)
    --when divisor is 0, return NULL to indicate
    --divide by 0
    / CAST(CASE dopc_base.cntr_value
    WHEN 0 THEN NULL
    ELSE dopc_base.cntr_value
    END AS FLOAT) AS cntr_value
    FROM sys.dm_os_performance_counters dopc_base
    JOIN sys.dm_os_performance_counters dopc_avgBulk
    ON dopc_base.cntr_type = @PERF_LARGE_RAW_BASE
    AND dopc_avgBulk.cntr_type = @PERF_AVERAGE_BULK
    AND dopc_base.object_name = dopc_avgBulk.object_name
    AND dopc_base.instance_name = dopc_avgBulk.instance_name
    --Average Wait Time has (ms) in name,
    --so it has handled "special"
    AND ( REPLACE(dopc_base.counter_name,
    'base', '') = dopc_avgBulk.counter_name
    OR REPLACE(dopc_base.counter_name,
    'base', '') = REPLACE(dopc_avgBulk.counter_name,
    '(ms)', '')
    )
    ORDER BY dopc_avgBulk.object_name ,
    dopc_avgBulk.instance_name ,
    dopc_avgBulk.counter_name
    
    CPU configuration details.
    
    -- Hardware information from SQL Server 2008
    -- (Cannot distinguish between HT and multi-core)
    SELECT cpu_count AS [Logical CPU Count] ,
    hyperthread_ratio AS [Hyperthread Ratio] ,
    cpu_count / hyperthread_ratio AS [Physical CPU Count] ,
    physical_memory_in_bytes / 1048576 AS [Physical Memory (MB)] ,
    sqlserver_start_time
    FROM sys.dm_os_sys_info ;
    
    Interrogating memory configuration.
    
    --Determine if this is a 32- or 64-bit SQL Server edition
    DECLARE @ServerAddressing AS TINYINT
    SELECT @serverAddressing = CASE WHEN CHARINDEX('64',
    CAST(SERVERPROPERTY('Edition')
    AS VARCHAR(100))) > 0
    THEN 64
    ELSE 32
    END ;
    SELECT cpu_count / hyperthread_ratio AS SocketCount ,
    physical_memory_in_bytes / 1024 / 1024 AS physical_memory_mb ,
    virtual_memory_in_bytes / 1024 / 1024 AS sql_max_virtual_memory_mb ,
    -- same with other bpool columns as they are page oriented.
    -- Multiplying by 8 takes it to 8K, then / 1024 to convert to mb
    bpool_committed * 8 / 1024 AS buffer_pool_committed_mb ,
    --64 bit OS does not have limitations with addressing as 32 did
    CASE WHEN @serverAddressing = 32
    THEN CASE WHEN virtual_memory_in_bytes / 1024 /
    ( 2048 * 1024 ) < 1
    THEN 'off'
    ELSE 'on'
    END
    ELSE 'N/A on 64 bit'
    END AS [/3GB switch]
    FROM sys.dm_os_sys_info
    
    Investigating scheduler activity.
    
    -- Get Avg task count and Avg runnable task count
    SELECT AVG(current_tasks_count) AS [Avg Task Count] ,
    AVG(runnable_tasks_count) AS [Avg Runnable Task Count]
    FROM sys.dm_os_schedulers
    WHERE scheduler_id < 255
    AND [status] = 'VISIBLE ONLINE' ;
    
    Investigating potential disk I/O or CPU pressure.
    
    SELECT scheduler_id ,
    cpu_id ,
    Status ,
    is_online ,
    is_idle ,
    current_tasks_count ,
    runnable_tasks_count ,
    current_workers_count ,
    active_workers_count ,
    work_queue_count ,
    pending_disk_io_count ,
    load_factor
    FROM sys.dm_os_schedulers
    WHERE scheduler_id < 255
    AND runnable_tasks_count > 0
    -- AND pending_disk_io_count > 0
    
    Are there sufficient worker threads for the workload?
    
    SELECT AVG(work_queue_count)
    FROM sys.dm_os_schedulers
    WHERE status = 'VISIBLE ONLINE'
    Investigating context switching.
    SELECT scheduler_id ,
    preemptive_switches_count ,
    context_switches_count ,
    idle_switches_count ,
    failed_to_create_worker
    FROM sys.dm_os_schedulers
    WHERE scheduler_id < 255
    Is NUMA enabled?
    -- Is NUMA enabled
    SELECT CASE COUNT(DISTINCT parent_node_id)
    WHEN 1 THEN 'NUMA disabled'
    ELSE 'NUMA enabled'
    END
    FROM sys.dm_os_schedulers
    WHERE parent_node_id <> 32 ;
    
    Recent CPU utilization.
    
    -- Get CPU Utilization History for last 30 minutes (in one minute intervals)
    -- This version works with SQL Server 2008 and SQL Server 2008 R2 only
    DECLARE @ts_now BIGINT = ( SELECT cpu_ticks / ( cpu_ticks / ms_ticks )
    FROM sys.dm_os_sys_info
    ) ;
    SELECT TOP ( 30 )
    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
    WHERE ring_buffer_type =
    N'RING_BUFFER_SCHEDULER_MONITOR'
    AND record LIKE N'%<SystemHealth>%'
    ) AS x
    ) AS y
    ORDER BY record_id DESC ;
    System memory usage.
    SELECT total_physical_memory_kb / 1024 AS total_physical_memory_mb ,
    available_physical_memory_kb / 1024 AS available_physical_memory_mb ,
    total_page_file_kb / 1024 AS total_page_file_mb ,
    available_page_file_kb / 1024 AS available_page_file_mb ,
    system_memory_state_desc
    FROM sys.dm_os_sys_memory
    
    Memory usage by the SQL Server process.
    
    SELECT physical_memory_in_use_kb ,
    virtual_address_space_committed_kb ,
    virtual_address_space_available_kb ,
    page_fault_count ,
    process_physical_memory_low ,
    process_virtual_memory_low
    FROM sys.dm_os_process_memory
    
    Memory allocation in the buffer pool.
    
    -- Get total buffer usage by database
    SELECT DB_NAME(database_id) AS [Database Name] ,
    COUNT(*) * 8 / 1024.0 AS [Cached Size (MB)]
    FROM sys.dm_os_buffer_descriptors
    WHERE database_id > 4 -- exclude system databases
    AND database_id <> 32767 -- exclude ResourceDB
    GROUP BY DB_NAME(database_id)
    ORDER BY [Cached Size (MB)] DESC ;
    -- Breaks down buffers by object (table, index) in the buffer pool
    SELECT OBJECT_NAME(p.[object_id]) AS [ObjectName] ,
    p.index_id ,
    COUNT(*) / 128 AS [Buffer size(MB)] ,
    COUNT(*) AS [Buffer_count]
    FROM sys.allocation_units AS a
    INNER JOIN sys.dm_os_buffer_descriptors
    AS b ON a.allocation_unit_id = b.allocation_unit_id
    INNER JOIN sys.partitions AS p ON a.container_id = p.hobt_id
    WHERE b.database_id = DB_ID()
    AND p.[object_id] > 100 -- exclude system objects
    GROUP BY p.[object_id] ,
    p.index_id
    ORDER BY buffer_count DESC ;
    
    Buffer pool usage.
    
    -- Buffer Pool Usage for instance
    SELECT TOP(20) [type], SUM(single_pages_kb) AS [SPA Mem, Kb]
    FROM sys.dm_os_memory_clerks
    GROUP BY [type]
    ORDER BY SUM(single_pages_kb) DESC;
    
    Which queries have requested, or have had to wait for, large memory grants?
    
    -- Shows the memory required by both running (non-null grant_time)
    -- and waiting queries (null grant_time)
    -- SQL Server 2008 version
    SELECT DB_NAME(st.dbid) AS [DatabaseName] ,
    mg.requested_memory_kb ,
    mg.ideal_memory_kb ,
    mg.request_time ,
    mg.grant_time ,
    mg.query_cost ,
    mg.dop ,
    st.[text]
    FROM sys.dm_exec_query_memory_grants AS mg
    CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
    WHERE mg.request_time < COALESCE(grant_time, '99991231')
    ORDER BY mg.requested_memory_kb DESC ;
    -- Shows the memory required by both running (non-null grant_time)
    -- and waiting queries (null grant_time)
    -- SQL Server 2005 version
    SELECT DB_NAME(st.dbid) AS [DatabaseName] ,
    mg.requested_memory_kb ,
    mg.request_time ,
    mg.grant_time ,
    mg.query_cost ,
    mg.dop ,
    st.[text]
    FROM sys.dm_exec_query_memory_grants AS mg
    CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS st
    WHERE mg.request_time < COALESCE(grant_time, '99991231')
    ORDER BY mg.requested_memory_kb DESC ;
    
    Returning the cache counters.
    
    SELECT type ,
    name ,
    single_pages_kb ,
    multi_pages_kb ,
    single_pages_in_use_kb ,
    multi_pages_in_use_kb ,
    entries_count ,
    entries_in_use_count
    FROM sys.dm_os_memory_cache_counters
    ORDER BY type,name;
    
    Investigating the use of the plan cache.
    
    SELECT name ,
    type ,
    entries_count ,
    entries_in_use_count
    FROM sys.dm_os_memory_cache_counters
    WHERE type IN ( 'CACHESTORE_SQLCP', 'CACHESTORE_OBJCP' )
    --ad hoc plans and object plans
    ORDER BY name ,
    type
    
    Investigating plan reuse counts.
    
    --in a different connection, execute this all at once:
    USE tempdb
    go
    CREATE PROCEDURE test
    AS
    WAITFOR DELAY '00:00:30'
    SELECT *
    FROM sys.sysobjects
    go
    EXECUTE test
    
    Resetting the latch statistics.
    
    DBCC SQLPERF ('sys.dm_os_latch_stats', CLEAR);
    
    Seeking out latch waits.
    
    SELECT latch_class ,
    waiting_requests_count AS waitCount ,
    wait_time_ms AS waitTime ,
    max_wait_time_ms AS maxWait
    FROM sys.dm_os_latch_stats
    ORDER BY wait_time_ms DESC
    Finding the top ten CPU-consuming queries
    
    SELECT TOP ( 10 )
    SUBSTRING(ST.text, ( QS.statement_start_offset / 2 ) + 1,
    ( ( CASE statement_end_offset
    WHEN -1 THEN DATALENGTH(st.text)
    ELSE QS.statement_end_offset
    END - QS.statement_start_offset ) / 2 ) + 1)
    AS statement_text ,execution_count ,
    total_worker_time / 1000 AS total_worker_time_ms ,
    ( total_worker_time / 1000 ) / execution_count
    AS avg_worker_time_ms ,
    total_logical_reads ,
    total_logical_reads / execution_count AS avg_logical_reads ,
    total_elapsed_time / 1000 AS total_elapsed_time_ms ,
    ( total_elapsed_time / 1000 ) / execution_count
    AS avg_elapsed_time_ms ,
    qp.query_plan
    FROM sys.dm_exec_query_stats qs
    CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
    CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
    ORDER BY total_worker_time DESC
    ————————————————
    版权声明:本文为CSDN博主「Burgess_Liu」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/Burgess_Liu/article/details/52813727

        

  • 相关阅读:
    xcode修改默认头部注释(__MyCompanyName__) (转)
    ios7注意事项随笔
    二分查找(BinarySearch)
    选择排序(SelectionSort)
    插入排序(InsertionSort)
    堆排序(HeapSort)
    归并排序(MergeSort)
    快速排序(QuickSort)
    基本-正则表达式
    2.5亿个整数中找出不重复的整数
  • 原文地址:https://www.cnblogs.com/chendian0/p/12146611.html
Copyright © 2011-2022 走看看