`

Tell me your secrets

 
阅读更多

请复制粘贴然后F5,经典无须多说!

复制代码
/*******************************************************************************************************

                    SQL SERVER 2005 - Tell me your secrets!

********************************************************************************************************

    Description: Report on the current performance health status of a SQL Server 2005 server using non-instrusive methods.

    Purpose: Identify areas where the database server as a whole can be improved, using data collected 
             by SQL Server itself. Many of these items apply to the database server as a whole, rather 
             than specific queries. 

    Author: Ian Stirk (Ian_Stirk@yahoo.com).

    Date: June 2007.

    Notes: This collection of SQL inspects various DMVs, this information can be used to highlight
           what areas of the SQL Server sever can be improved. The following items are reported on:
  
                1. Causes of the server waits
                2. Databases using the most IO
                3. Count of missing indexes, by database
                4. Most important missing indexes
                5. Unused Indexes
                6. Most costly indexes (high maintenance)
                7. Most used indexes
                8. Most fragmented indexes
                9. Most costly queries, by average IO
                10. Most costly queries, by average CPU
                11. Most costly CLR queries, by average CLR time
                12. Most executed queries
                13. Queries suffering most from blocking
                14. Queries with the lowest plan reuse

********************************************************************************************************

PRE-REQUISITE
1. Best to have as much DMV data as possible (When last rebooted? Want daily? weekly, monthly, quarterly results).
2. Output HSR to Grid? Text? File? Table? Reporting Services? If set results to text, get the actual sprocs in output.
3. Decide if want to put results in a database? Later analysis, historical comparisons, impact of month-end, quarter etc. 
4. Decide if want to run the defrag code, can be expensive.
5. Decide if want to iterate over all databases for a specific aspect (e.g. average IO).


FOLLOW-UP (After running this routine's SQL)
1. Investigative work, use dba_SearchDB/dba_SearchDBServer for analysis.
2. Demonstrate/measure the improvement: Find underlying queries, apply change, run stats IO ON, see execuation plan.
3. SQL Server Best Practices Analyzer.


INTRUSIVE INSPECTION (Follow-up and corollary to this work)
1. Trace typical workload (day, monthend? etc)
2. Reduce recorded queries to query signatures (Ben-Gan's method)
3. Calculate the total duration for similar query patterns
4. Tune the most important query patterns in DTA, then apply recommended indexes/stats.

*********************************************************************************************************/

-- Do not lock anything, and do not get held up by any locks. 
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


SELECT 'Identify what is causing the waits.' AS [Step01];
/************************************************************************************/
/* STEP01.                                                                            */
/* Purpose: Identify what is causing the waits.                                        */
/* Notes: 1.                                                                        */
/************************************************************************************/
SELECT TOP 10
    [Wait type] = wait_type,
    [Wait time (s)] = wait_time_ms / 1000,
    [% waiting] = CONVERT(DECIMAL(12,2), wait_time_ms * 100.0 / SUM(wait_time_ms) OVER())
FROM sys.dm_os_wait_stats
WHERE wait_type NOT LIKE '%SLEEP%' 
--AND wait_type NOT LIKE 'CLR_%'
ORDER BY wait_time_ms DESC;


SELECT 'Identify what databases are reading the most logical pages.' AS [Step02a];
/************************************************************************************/
/* STEP02a.                                                                            */
/* Purpose: Identify what databases are reading the most logical pages.                */
/* Notes : 1. This should highlight the databases to target for best improvement.    */
/*           2. Watch out for tempDB, a high value is suggestive.                        */    
/************************************************************************************/
-- Total reads by DB
SELECT TOP 10 
        [Total Reads] = SUM(total_logical_reads)
        ,[Execution count] = SUM(qs.execution_count)
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
GROUP BY DB_NAME(qt.dbid)
ORDER BY [Total Reads] DESC;


SELECT 'Identify what databases are writing the most logical pages.' AS [Step02b];
/************************************************************************************/
/* STEP02b.                                                                            */
/* Purpose: Identify what databases are writing the most logical pages.                */
/* Notes : 1. This should highlight the databases to target for best improvement.    */
/*           2. Watch out for tempDB, a high value is suggestive.                        */    
/************************************************************************************/
-- Total Writes by DB
SELECT TOP 10 
        [Total Writes] = SUM(total_logical_writes)
        ,[Execution count] = SUM(qs.execution_count)
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
GROUP BY DB_NAME(qt.dbid)
ORDER BY [Total Writes] DESC;


SELECT 'Count of missing indexes, by databases.' AS [Step03];
/************************************************************************** ******************/
/* STEP03.                                                                            */
/* Purpose: Identify the number of missing (or incomplete indexes), across ALL databases.     */
/* Notes : 1. This should highlight the databases to target for best improvement.             */
/*********************************************************************************************/
SELECT 
    DatabaseName = DB_NAME(database_id)
    ,[Number Indexes Missing] = count(*) 
FROM sys.dm_db_missing_index_details
GROUP BY DB_NAME(database_id)
ORDER BY 2 DESC;


SELECT 'Identify the missing indexes (TOP 10), across ALL databases.' AS [Step04];
/****************************************************************************************************/
/* STEP04.                                                                            */
/* Purpose: Identify the missing (or incomplete indexes) (TOP 20), for ALL databases.                */
/* Notes : 1. Could combine above with number of reads/writes a DB has since reboot, but this takes */
/*           into account how often index could have been used, and estimates a 'realcost'            */
/****************************************************************************************************/
SELECT  TOP 10 
        [Total Cost]  = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0) 
        , avg_user_impact -- Query cost would reduce by this amount, on average.
        , TableName = statement
        , [EqualityUsage] = equality_columns 
        , [InequalityUsage] = inequality_columns
        , [Include Cloumns] = included_columns
FROM        sys.dm_db_missing_index_groups g 
INNER JOIN    sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle 
INNER JOIN    sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle
ORDER BY [Total Cost] DESC;


SELECT 'Identify which indexes are not being used, across ALL databases.' AS [Step05];
/*******************************************************************************************************/
/* STEP05.                                                                            */
/* Purpose: Identify which indexes are not being used, for a given database.                            */
/* Notes: 1. These will have a deterimental impact on any updates/deletions.                            */
/*          Remove if possible (can see the updates in user_updates and system_updates fields)            */
/*          2. Systems means DBCC commands, DDL commands, or update statistics - so can typically ignore.    */
/*          3. The template below uses the sp_MSForEachDB, this is because joining on sys.databases        */
/*            gives incorrect results (due to sys.indexes taking into account the current database only).    */     
/********************************************************************************************************/
-- Create required table structure only.
-- Note: this SQL must be the same as in the Database loop given in following step.
SELECT TOP 1
        DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        ,user_updates    
        ,system_updates    
        -- Useful fields below:
        --, *
INTO #TempUnusedIndexes
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id 
WHERE  s.database_id = DB_ID()
    AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
    AND    user_seeks = 0
    AND user_scans = 0 
    AND user_lookups = 0
    -- Below may not be needed, they tend to reflect creation of stats, backups etc...
--    AND    system_seeks = 0
--    AND system_scans = 0
--    AND system_lookups = 0
    AND s.[object_id] = -999  -- Dummy value, just to get table structure.
;

-- Loop around all the databases on the server.
EXEC sp_MSForEachDB    'USE [?]; 
-- Table already exists.
INSERT INTO #TempUnusedIndexes 
SELECT TOP 10    
        DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        ,user_updates    
        ,system_updates    
        -- Useful fields below:
        --, *
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id 
WHERE  s.database_id = DB_ID()
    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
    AND    user_seeks = 0
    AND user_scans = 0 
    AND user_lookups = 0
    AND i.name IS NOT NULL    -- I.e. Ignore HEAP indexes.
    -- Below may not be needed, they tend to reflect creation of stats, backups etc...
--    AND    system_seeks = 0
--    AND system_scans = 0
--    AND system_lookups = 0
ORDER BY user_updates DESC
;
'

-- Select records.
SELECT TOP 10 *  FROM #TempUnusedIndexes ORDER BY [user_updates]  DESC
-- Tidy up.
DROP TABLE #TempUnusedIndexes


SELECT 'Identify which indexes are the most high maintenance (TOP 10), across ALL databases.' AS [Step06];
/********************************************************************************************************/
/* STEP06.                                                                            */
/* Purpose: Identify which indexes are the most high maintenance (TOP 10), for a given database.        */
/* Notes: 1. These indexes are updated the most, may want to review if the are necessary.                */
/*        2. Another version shows writes per read.                                                          */
/*          3. Systems means DBCC commands, DDL commands, or update statistics - so can typically ignore. */
/*          4. The template below uses the sp_MSForEachDB, this is because joining on sys.databases        */
/*            gives incorrect results (due to sys.indexes taking into account the current database only).    */     
/********************************************************************************************************/
-- Create required table structure only.
-- Note: this SQL must be the same as in the Database loop given in following step.
SELECT TOP 1
        [Maintenance cost]  = (user_updates + system_updates)
        ,[Retrieval usage] = (user_seeks + user_scans + user_lookups)
        ,DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        -- Useful fields below:
--        ,user_updates  
--        ,system_updates
--        ,user_seeks 
--        ,user_scans 
--        ,user_lookups 
--        ,system_seeks 
--        ,system_scans 
--        ,system_lookups 
        -- Useful fields below:
--        ,*
INTO #TempMaintenanceCost
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id
WHERE s.database_id = DB_ID() 
    AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
    AND (user_updates + system_updates) > 0 -- Only report on active rows.
    AND s.[object_id] = -999  -- Dummy value, just to get table structure.
;

-- Loop around all the databases on the server.
EXEC sp_MSForEachDB    'USE [?]; 
-- Table already exists.
INSERT INTO #TempMaintenanceCost 
SELECT TOP 10
        [Maintenance cost]  = (user_updates + system_updates)
        ,[Retrieval usage] = (user_seeks + user_scans + user_lookups)
        ,DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        -- Useful fields below:
--        ,user_updates  
--        ,system_updates
--        ,user_seeks 
--        ,user_scans 
--        ,user_lookups 
--        ,system_seeks 
--        ,system_scans 
--        ,system_lookups 
        -- Useful fields below:
--        ,*
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON  s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id
WHERE s.database_id = DB_ID() 
    AND i.name IS NOT NULL    -- I.e. Ignore HEAP indexes.
    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
    AND (user_updates + system_updates) > 0 -- Only report on active rows.
ORDER BY [Maintenance cost]  DESC
;
'

-- Select records.
SELECT TOP 10 *  FROM #TempMaintenanceCost ORDER BY [Maintenance cost]  DESC
-- Tidy up.
DROP TABLE #TempMaintenanceCost


SELECT 'Identify which indexes are the most often used (TOP 10), across ALL databases.' AS [Step07];
/********************************************************************************************************/
/* STEP07.                                                                            */
/* Purpose: Identify which indexes are the most used (TOP 10), for a given database.                     */
/* Notes: 1. These indexes are updated the most, may want to review if the are necessary.                   */
/*          2. Systems means DBCC commands, DDL commands, or update statistics - so can typically ignore. */
/*          3. Ensure Statistics are up-to-date for these.                                                 */
/*          4. The template below uses the sp_MSForEachDB, this is because joining on sys.databases        */
/*            gives incorrect results (due to sys.indexes taking into account the current database only).    */     
/********************************************************************************************************/

-- Create required table structure only.
-- Note: this SQL must be the same as in the Database loop given in following step.
SELECT TOP 1
        [Usage] = (user_seeks + user_scans + user_lookups)
        ,DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        -- Useful fields below:
--        ,user_updates  
--        ,system_updates
--        ,user_seeks 
--        ,user_scans 
--        ,user_lookups 
--        ,system_seeks 
--        ,system_scans 
--        ,system_lookups 
        -- Useful fields below:
        --, *
INTO #TempUsage
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id 
WHERE   s.database_id = DB_ID() 
    AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
    AND (user_seeks + user_scans + user_lookups) > 0 -- Only report on active rows.
    AND s.[object_id] = -999  -- Dummy value, just to get table structure.
;

-- Loop around all the databases on the server.
EXEC sp_MSForEachDB    'USE [?]; 
-- Table already exists.
INSERT INTO #TempUsage 
SELECT TOP 10
        [Usage] = (user_seeks + user_scans + user_lookups)
        ,DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        -- Useful fields below:
--        ,user_updates  
--        ,system_updates
--        ,user_seeks 
--        ,user_scans 
--        ,user_lookups 
--        ,system_seeks 
--        ,system_scans 
--        ,system_lookups 
        -- Useful fields below:
        --, *
FROM   sys.dm_db_index_usage_stats s 
INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id 
WHERE   s.database_id = DB_ID() 
    AND i.name IS NOT NULL    -- I.e. Ignore HEAP indexes.
    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
    AND (user_seeks + user_scans + user_lookups) > 0 -- Only report on active rows.
ORDER BY [Usage]  DESC
;
'

-- Select records.
SELECT TOP 10 * FROM #TempUsage ORDER BY [Usage] DESC
-- Tidy up.
DROP TABLE #TempUsage


SELECT 'Identify which indexes are the most logically fragmented (TOP 10), across ALL databases.' AS [Step08];
/********************************************************************************************/
/* STEP08.                                                                            */
/* Purpose: Identify which indexes are the most fragmented (TOP 10), for a given database.  */
/* Notes: 1. Defragmentation increases IO.                                                    */
/********************************************************************************************/
---- Create required table structure only.
---- Note: this SQL must be the same as in the Database loop given in following step.
--SELECT TOP 1 
--        DatbaseName = DB_NAME()
--        ,TableName = OBJECT_NAME(s.[object_id])
--        ,IndexName = i.name
--        ,[Fragmentation %] = ROUND(avg_fragmentation_in_percent,2)
--        -- Useful fields below:
--        --, *
--INTO #TempFragmentation
--FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s
--INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
--    AND s.index_id = i.index_id 
--WHERE s.[object_id] = -999  -- Dummy value, just to get table structure.
--;
--
---- Loop around all the databases on the server.
--EXEC sp_MSForEachDB    'USE [?]; 
---- Table already exists.
--INSERT INTO #TempFragmentation 
--SELECT TOP 10
--        DatbaseName = DB_NAME()
--        ,TableName = OBJECT_NAME(s.[object_id])
--        ,IndexName = i.name
--        ,[Fragmentation %] = ROUND(avg_fragmentation_in_percent,2)
--        -- Useful fields below:
--        --, *
--FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s
--INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] 
--    AND s.index_id = i.index_id 
--WHERE s.database_id = DB_ID() 
--      AND i.name IS NOT NULL    -- I.e. Ignore HEAP indexes.
--    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0
--ORDER BY [Fragmentation %] DESC
--;
--'
--
---- Select records.
--SELECT TOP 10 * FROM #TempFragmentation ORDER BY [Fragmentation %] DESC
---- Tidy up.
--DROP TABLE #TempFragmentation


SELECT 'Identify which (cached plan) queries are the most costly by average IO (TOP 10), across ALL databases.' AS [Step09];
/****************************************************************************************************/
/* STEP09.                                                                            */
/* Purpose: Identify which queries are the most costly by IO (TOP 10), across ALL databases.        */
/* Notes: 1. This could be areas that need optimisation, maybe they crosstab with missing indexes?  */
/*          2. Decide if average or total is more important.                                            */
/****************************************************************************************************/
SELECT TOP 10 
        [Average IO] = (total_logical_reads + total_logical_writes) / qs.execution_count
        ,[Total IO] = (total_logical_reads + total_logical_writes)
        ,[Execution count] = qs.execution_count
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) 
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
--WHERE DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY [Average IO] DESC;


SELECT 'Identify which (cached plan) queries are the most costly by average CPU (TOP 10), across ALL databases.' AS [Step10];
/****************************************************************************************************/
/* STEP10.                                                                            */
/* Purpose: Identify which queries are the most costly by CPU (TOP 10), across ALL databases.        */
/* Notes: 1. This could be areas that need optimisation, maybe they crosstab with missing indexes?  */
/*          2. Decide if average or total is more important.                            */
/****************************************************************************************************/
SELECT TOP 10 
        [Average CPU used] = total_worker_time / qs.execution_count
        ,[Total CPU used] = total_worker_time
        ,[Execution count] = qs.execution_count
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
--WHERE DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY [Average CPU used] DESC;


SELECT 'Identify which CLR queries, use the most average CLR time (TOP 10), across ALL databases.' AS [Step11];
/****************************************************************************************************/
/* STEP011.                                                                            */
/* Purpose: Identify which CLR queries, use the most avg CLR time (TOP 10), across ALL databases.   */
/* Notes: 1. Decide if average or total is more important.                                            */
/****************************************************************************************************/
SELECT TOP 10 
        [Average CLR Time] = total_clr_time / execution_count 
        ,[Total CLR Time] = total_clr_time 
        ,[Execution count] = qs.execution_count
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
        -- Useful fields below:
        --, *
FROM sys.dm_exec_query_stats as qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
WHERE total_clr_time <> 0
--AND DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY [Average CLR Time] DESC;


SELECT 'Identify which (cached plan) queries are executed most often (TOP 10), across ALL databases.' AS [Step12];
/********************************************************************************************/
/* STEP12.                                                                            */
/* Purpose: Identify which queries are executed most often (TOP 10), across ALL databases.  */
/* Notes: 1. These should be optimised. Ensure Statistics are up to date.                    */
/********************************************************************************************/
SELECT TOP 10 
        [Execution count] = execution_count
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
--AND DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY [Execution count] DESC;


SELECT 'Identify which (cached plan) queries suffer the most from blocking (TOP 10), across ALL databases.' AS [Step13];
/****************************************************************************************************/
/* STEP13.                                                                            */
/* Purpose: Identify which queries suffer the most from blocking (TOP 10), across ALL databases.    */
/* Notes: 1. This may have an impact on ALL queries.                                                */
/*          2. Decide if average or total is more important.                                            */
/****************************************************************************************************/
SELECT TOP 10 
        [Average Time Blocked] = (total_elapsed_time - total_worker_time) / qs.execution_count
        ,[Total Time Blocked] = total_elapsed_time - total_worker_time 
        ,[Execution count] = qs.execution_count
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) 
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
--AND DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY [Average Time Blocked] DESC;


SELECT 'What (cached plan) queries have the lowest plan reuse (Top 10), across ALL databases.' AS [Step14];
/************************************************************************************/
/* STEP14.                                                                            */
/* What queries, in the current database, have the lowest plan reuse (Top 10).        */
/* Notes: 1.                                                                          */
/************************************************************************************/
SELECT TOP 10
        [Plan usage] = cp.usecounts
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
        ,cp.cacheobjtype
        -- Useful fields below:
        --, *
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
INNER JOIN sys.dm_exec_cached_plans as cp on qs.plan_handle=cp.plan_handle
WHERE cp.plan_handle=qs.plan_handle
--AND DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY [Plan usage] ASC;


-- MIGHT BE USEFUL
/*


/* ALTERNATIVE. */
SELECT 'Identify what indexes have a high maintenance cost.' AS [Step];
/* Purpose: Identify what indexes have a high maintenance cost. */
/* Notes : 1. This version shows writes per read, another version shows total updates without reads. */
SELECT     TOP 10
        DatabaseName = DB_NAME()
        ,TableName = OBJECT_NAME(s.[object_id])
        ,IndexName = i.name
        ,[Writes per read (User)] = user_updates / CASE WHEN (user_seeks + user_scans + user_lookups) = 0 
                                                            THEN 1 
                                                       ELSE (user_seeks + user_scans + user_lookups) 
                                                   END 
        ,[User writes] = user_updates
        ,[User reads] = user_seeks + user_scans + user_lookups
        ,[System writes] = system_updates
        ,[System reads] = system_seeks + system_scans + system_lookups
        -- Useful fields below:
        --, *
FROM   sys.dm_db_index_usage_stats s 
        , sys.indexes i 
WHERE   s.[object_id] = i.[object_id] 
    AND s.index_id = i.index_id 
    AND s.database_id = DB_ID()
    AND OBJECTPROPERTY(s.[object_id], 'IsMsShipped') = 0
ORDER BY [Writes per read (User)] DESC;


-- Total Reads by most expensive IO query
SELECT TOP 10 
        [Total Reads] = total_logical_reads
        ,[Total Writes] = total_logical_writes
        ,[Execution count] = qs.execution_count
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) 
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
ORDER BY [Total Reads] DESC;

-- Total Writes by most expensive IO query
SELECT TOP 10 
        [Total Writes] = total_logical_writes
        ,[Total Reads] = total_logical_reads
        ,[Execution count] = qs.execution_count
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt
ORDER BY [Total Writes] DESC;




-- Most reused queries...
SELECT TOP 10 
        [Run count] = usecounts
        ,[Query] = text
        ,DatabaseName = DB_NAME(qt.dbid)
        ,*
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) as qt
--AND DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY 1 DESC;

-- The below does not give the same values as previosu step, maybe related to 
-- individual qry within the parent qry? 
SELECT TOP 10 
        [Run count] = usecounts
        ,[Individual Query] = SUBSTRING (qt.text,qs.statement_start_offset/2, 
         (CASE WHEN qs.statement_end_offset = -1 
            THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 
          ELSE qs.statement_end_offset END - qs.statement_start_offset)/2)
        ,[Parent Query] = qt.text
        ,DatabaseName = DB_NAME(qt.dbid)
        ,*
FROM sys.dm_exec_cached_plans cp
INNER JOIN sys.dm_exec_query_stats qs ON cp.plan_handle = qs.plan_handle
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) as qt
--AND DB_NAME(qt.dbid) = 'pnl'  -- Filter on a given database.
ORDER BY 1 DESC;

*/
复制代码


引用连接:http://msdn.microsoft.com/en-us/magazine/cc135978.aspx?pr=blog

分享到:
评论

相关推荐

    Stamina Secrets Increase Your Penis

    Stamina Secrets Increase Your Penis & Stronger Erections for latest version in 2013

    CSS Secrets CSS 魔法

    CSS Secrets 一书是专为那些正从中级向高级进阶的CSS开发者所准备的,书中涵盖了47个未公开的技巧和技术。这些技巧可以帮助开发者优雅地解决日常网页设计问题,而不仅仅是聚焦于设计本身。作者Lea Verou,作为CSS...

    Secrets of Self Made Millonaires

    Secrets of Self Made Millonaires

    python标准库之secrets.docx

    这个模块的出现是为了提供一种更安全的方式来生成这些机密数据,相比 `random` 模块,`secrets` 使用了更高级别的随机数生成机制,确保了生成的随机数具有足够的熵,难以被预测。 `secrets` 模块中的主要功能包括:...

    Microsoft Secrets

    "Microsoft Secrets"这个标题暗示了我们要探讨的是那些不为大众所知,但对理解微软及其成功至关重要的内部运作、策略和创新。描述中的“Secrets about Microsoft”更是直指其核心,让我们一起揭开这家科技巨头的神秘...

    PyPI 官网下载 | detect_secrets-0.11.3.tar.gz

    《PyPI官网下载 | detect_secrets-0.11.3.tar.gz——Python安全检测库详解》 在Python的世界里,PyPI(Python Package Index)是开发者获取和分享开源软件包的重要平台。今天我们将深入探讨PyPI上的一款名为`detect...

    The Secrets Of Economic Indicators

    The Secrets Of Economic Indicators

    Secrets of Reverse Engineering

    "Secrets of Reverse Engineering"很可能是一份关于这一主题的深入学习资源,包含丰富的理论知识与实践技巧。 逆向工程的基本流程通常包括以下几个步骤: 1. 获取目标:这可能是一个可执行文件、库、固件或任何...

    CSS SECRETS BETTER SOLUTIONS TO EVERYDAY WEB DESIGN PROBLEMS

    本书《CSS SECRETS: BETTER SOLUTIONS TO EVERYDAY WEB DESIGN PROBLEMS》由Lea Verou撰写,是一本面向新一代CSS的著作。作者不仅是设计师,同时也是前端开发者,她在CSS界有着丰富的经验和权威地位。本书不仅仅停留...

    PyPI 官网下载 | cdk8s-sealed-secrets-controller-0.0.1.tar.gz

    《PyPI官网下载:深入解析cdk8s-sealed-secrets-controller-0.0.1》 在Python的生态系统中,PyPI(Python Package Index)是最重要的资源库,它为开发者提供了海量的开源库和模块,以供他们在项目中使用。本次我们...

    HACKING SECRETS REVEALED

    HACKING SECRETS REVEALED

    Programming Interviews Exposed_Secrets to Landing Your Next Job

    《Programming Interviews Exposed: Secrets to Landing Your Next Job》(编程面试揭秘:成功获取心仪工作的秘诀)是一本专门为计算机科学专业的本科生以及有经验的程序员设计的书籍。本书不仅对在校学生有所帮助,...

    Reversing Secrets of Reverse Engineering.rar

    Reversing Secrets of Reverse Engineering.rar

    Windows95 System Programming Secrets.pdf

    #### 标题:Windows 95 System Programming Secrets **知识点一:系统编程的深度探索** 本书名为《Windows 95 System Programming Secrets》,意味着它将深入探讨Windows 95操作系统下的系统编程技术与秘密。通过...

    CSS Secrets(正式版,原版pdf)

    《CSS Secrets》是一本由Lea Verou编著的书籍,专注于解决Web设计中的日常问题。这本书的中文标题是“CSS Secrets(正式版,原版pdf)”,它提供了第一版的内容,确保读者能够获取到最权威和最新的CSS技术信息。CSS ...

    Python库 | python_secrets-22.1.0-py3.8.egg

    资源分类:Python库 所属语言:Python 资源全名:python_secrets-22.1.0-py3.8.egg 资源来源:官方 安装方法:https://lanzao.blog.csdn.net/article/details/101784059

    Subnetting Secrets 无水印转化版pdf

    Subnetting Secrets 英文无水印转化版pdf pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和Firefox测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国...

    Go-搜索全部Git仓库历史的secrets和密钥

    搜索全部Git仓库历史的secrets和密钥

    Undocumented Windows 2000 Secrets 源码

    源码文件列表中的"Addison Wesley - Sven Schreiber - Undocumented Windows 2000 Secrets [src]"很可能包含了多个章节的源代码示例,这些示例涵盖了以下几个关键知识点: 1. **系统调用接口**:Windows 2000操作...

Global site tag (gtag.js) - Google Analytics