DMVsinSQLServer -- 备
/*******************************************************************************************************
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
DMVsinSQLServer -- 备的更多相关文章
- Oracle冷备迁移脚本(文件系统)
Oracle冷备迁移脚本(文件系统) 两个脚本: 配置文件生成脚本dbinfo.sh 网络拷贝到目标服务器的脚本cpdb16.sh 1. 配置文件生成脚本 #!/bin/bash #Usage: cr ...
- GIS部分理论知识备忘随笔
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.高斯克吕格投影带换算 某坐标的经度为112度,其投影的6度带和3度带 ...
- mysql+mycat搭建稳定高可用集群,负载均衡,主备复制,读写分离
数据库性能优化普遍采用集群方式,oracle集群软硬件投入昂贵,今天花了一天时间搭建基于mysql的集群环境. 主要思路 简单说,实现mysql主备复制-->利用mycat实现负载均衡. 比较了 ...
- CentOS系统MySQL双机热备配置
1 概述 在集成项目中需要应对不同环境下的安装配置,主流操作系统大致可以分为三种:Linux.Windows以及UNIX.其中Linux备受青睐的主要原因有两个: 首先,Linux作为自由软件有两个 ...
- python序列,字典备忘
初识python备忘: 序列:列表,字符串,元组len(d),d[id],del d[id],data in d函数:cmp(x,y),len(seq),list(seq)根据字符串创建列表,max( ...
- 一张“神图”看懂单机/集群/热备/磁盘阵列(RAID)
单机部署(stand-alone):只有一个饮水机提供服务,服务只部署一份 集群部署(cluster):有多个饮水机同时提供服务,服务冗余部署,每个冗余的服务都对外提供服务,一个服务挂掉时依然可用 热 ...
- mysql主备(centos6.4)
服务器基本环境: 两台centos6.4.iptables diabled .selinux disabled 两台的hosts解析 #yum install mysql -y //这个一定要装 ...
- Keepalived+LVS+nginx双机热备
Keepalived简介 什么是Keepalived呢,keepalived观其名可知,保持存活,在网络里面就是保持在线了, 也就是所谓的高可用或热备,用来防止单点故障的发生. Keepalived采 ...
- Oracle备库TNS连接失败的分析
今天在测试12c的temp_undo的时候,准备在备库上测试一下,突然发现备库使用TNS连接竟然失败. 抛出的错误如下: $ sqlplus sys/oracle@testdb as sysdba S ...
随机推荐
- PHP的五种常见设计模式
工厂模式 最初在设计模式 一书中,许多设计模式都鼓励使用松散耦合.要理解这个概念,让我们最好谈一下许多开发人员从事大型系统的艰苦历程.在更改一个代码片段时,就会发生问题,系统其他部分 —— 您曾认为完 ...
- PHP获取毫秒时间戳
我们知道,PHP中time()函数获取的时间戳,其单位是秒. 但是,前端JS获取的时间戳,单位是毫秒. 那么,在实际应用中,如何将JS和PHP的时间戳统一,即如何使用PHP获取毫秒时间戳呢,请看下例: ...
- 解除被DenyHosts锁定的IP地址
自己的本本无法ssh上服务器,提示 ssh_exchange_identification: read: Connection reset by peer 仔细回想,自己手贱把~下面的一个ssh文件删 ...
- C++流操作之fstream
在Windows平台对文件进行存取操作可选的方案有很多,如果采用纯C,则需要用到File*等,当然也可以直接调用Windows API来做:如果采用C++,首先想到的就是文件流fstream.虽然在C ...
- python 的一些高级编程技巧
正文: 本文展示一些高级的Python设计结构和它们的使用方法.在日常工作中,你可以根据需要选择合适的数据结构,例如对快速查找性的要求.对数据一致性的要求或是对索引的要求等,同时也可以将各种数据结构合 ...
- iOS 开发常用设置
1. iOS设置app应用程序文件共享 设置流程 xcode 打开项目----在 info.plist 文件,添加 UIFileSharingEnabled 并设置属性为 YES, 在app内部,将您 ...
- Android开发之自定义Spinner样式的效果实现(源代码实现)
android系统自带的Spinner样式是远远满足不了我们实际开发过程中对Spinner UI风格的要求,因此我们肯定需要为了切合整个应用的风格,修改我们的Spinner样式.系统给我们提供了两种常 ...
- sctf pwn200
题目给出了pwn200和libc.so.使用IDA查看程序,发现逻辑很简单. 使用checksec查看pwn200的安全属性,如下图: 发现NX enabled,No PIE. 在第一次读(0x080 ...
- Global.asax 文件说明
引用 来自 http://www.cnblogs.com/jianshao810/archive/2011/02/03/1948912.htm 在网上找了N多相关的东西总说的不够细,现在终于找到了. ...
- lightoj 1079 Just another Robbery
题意:给出银行的个数和被抓概率上限.在给出每个银行的钱和抢劫这个银行被抓的概率.求不超过被抓概率上线能抢劫到最多的钱. dp题,转移方程 dp[i][j] = min(dp[i-1][j] , dp[ ...