转自:http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html#commentform

有关索引的DMV

1.查看那些被大量更新,却很少被使用的索引

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
SELECT                                                    
    DB_NAME() AS DatabaseName 
    , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , s.user_updates 
    , s.system_seeks + s.system_scans + s.system_lookups 
                          AS [System usage] 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE 1=2 
EXEC sp_MSForEachDB 'USE [?];                           
INSERT INTO #TempUnusedIndexes 
SELECT TOP 20 
    DB_NAME() AS DatabaseName 
    , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , s.user_updates 
    , s.system_seeks + s.system_scans + s.system_lookups 
                                         AS [System usage] 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE s.database_id = DB_ID() 
AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 
AND s.user_seeks = 0 
    AND s.user_scans = 0 
    AND s.user_lookups = 0 
AND i.name IS NOT NULL 
ORDER BY s.user_updates DESC'                            
SELECT TOP 20 * FROM #TempUnusedIndexes ORDER BY [user_updates] DESC 
DROP TABLE #TempUnusedIndexes

结果如图:

这类索引应该被Drop掉

最高维护代价的索引

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
SELECT                                                     
    DB_NAME() AS DatabaseName 
    , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , (s.user_updates ) AS [update usage] 
    , (s.user_seeks + s.user_scans + s.user_lookups) AS [Retrieval usage] 
    , (s.user_updates) - 
      (s.user_seeks + s.user_scans + s.user_lookups) AS [Maintenance cost] 
    , s.system_seeks + s.system_scans + s.system_lookups AS [System usage] 
    , s.last_user_seek 
    , s.last_user_scan 
    , s.last_user_lookup 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE 1=2 
EXEC sp_MSForEachDB 'USE [?];                              
INSERT INTO #TempMaintenanceCost 
SELECT TOP 20 
    DB_NAME() AS DatabaseName 
    , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , (s.user_updates ) AS [update usage] 
    , (s.user_seeks + s.user_scans + s.user_lookups) 
                    AS [Retrieval usage] 
    , (s.user_updates) - 
(s.user_seeks + user_scans + 
                         s.user_lookups) AS [Maintenance cost] 
    , s.system_seeks + s.system_scans + s.system_lookups AS [System usage] 
    , s.last_user_seek 
    , s.last_user_scan 
    , s.last_user_lookup 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE s.database_id = DB_ID() 
    AND i.name IS NOT NULL 
    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 
    AND (s.user_seeks + s.user_scans + s.user_lookups) > 0 
ORDER BY [Maintenance cost] DESC'                        
SELECT top 20 * FROM #TempMaintenanceCost ORDER BY [Maintenance cost] DESC 
DROP TABLE #TempMaintenanceCost

结果如图:

Maintenance cost高的应该被Drop掉

使用频繁的索引

--使用频繁的索引 
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
SELECT                                           
    DB_NAME() AS DatabaseName 
        , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , (s.user_seeks + s.user_scans + s.user_lookups) AS [Usage] 
    , s.user_updates 
    , i.fill_factor 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE 1=2 
EXEC sp_MSForEachDB 'USE [?];                               
INSERT INTO #TempUsage 
SELECT TOP 20 
    DB_NAME() AS DatabaseName 
    , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , (s.user_seeks + s.user_scans + s.user_lookups) AS [Usage] 
    , s.user_updates 
    , i.fill_factor 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE s.database_id = DB_ID() 
    AND i.name IS NOT NULL 
    AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 
ORDER BY [Usage] DESC'                                    
SELECT TOP 20 * FROM #TempUsage ORDER BY [Usage] DESC 
DROP TABLE #TempUsage

结果如图

这类索引需要格外注意,不要在优化的时候干掉

碎片最多的索引

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
SELECT                                                     
    DB_NAME() AS DatbaseName 
    , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , ROUND(s.avg_fragmentation_in_percent,2) AS [Fragmentation %] 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE 1=2 
EXEC sp_MSForEachDB 'USE [?];                                
INSERT INTO #TempFragmentation 
SELECT TOP 20 
    DB_NAME() AS DatbaseName 
    , SCHEMA_NAME(o.Schema_ID) AS SchemaName 
    , OBJECT_NAME(s.[object_id]) AS TableName 
    , i.name AS IndexName 
    , ROUND(s.avg_fragmentation_in_percent,2) AS [Fragmentation %] 
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 
INNER JOIN sys.objects o ON i.object_id = O.object_id    
WHERE s.database_id = DB_ID() 
  AND i.name IS NOT NULL 
  AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 
ORDER BY [Fragmentation %] DESC'                          
SELECT top 20 * FROM #TempFragmentation ORDER BY [Fragmentation %] DESC 
DROP TABLE #TempFragmentation

结果如下:

这类索引需要Rebuild,否则会严重拖累数据库性能

自上次SQL Server重启后,找出完全没有使用的索引

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
SELECT                                                 
    DB_NAME() AS DatbaseName 
    , SCHEMA_NAME(O.Schema_ID) AS SchemaName 
    , OBJECT_NAME(I.object_id) AS TableName 
    , I.name AS IndexName 
INTO #TempNeverUsedIndexes 
FROM sys.indexes I INNER JOIN sys.objects O ON I.object_id = O.object_id 
WHERE 1=2 
EXEC sp_MSForEachDB 'USE [?];                           
INSERT INTO #TempNeverUsedIndexes 
SELECT 
    DB_NAME() AS DatbaseName 
    , SCHEMA_NAME(O.Schema_ID) AS SchemaName 
    , OBJECT_NAME(I.object_id) AS TableName 
    , I.NAME AS IndexName 
FROM sys.indexes I INNER JOIN sys.objects O ON I.object_id = O.object_id 
LEFT OUTER JOIN sys.dm_db_index_usage_stats S ON S.object_id = I.object_id 
        AND I.index_id = S.index_id 
        AND DATABASE_ID = DB_ID() 
WHERE OBJECTPROPERTY(O.object_id,''IsMsShipped'') = 0 
  AND I.name IS NOT NULL 
  AND S.object_id IS NULL' 
SELECT * FROM #TempNeverUsedIndexes                         
ORDER BY DatbaseName, SchemaName, TableName, IndexName 
DROP TABLE #TempNeverUsedIndexes

结果如图:

这类索引应该小心对待,不能一概而论,要看是什么原因导致这种问题

查看索引统计的相关信息

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED 
SELECT 
    ss.name AS SchemaName 
    , st.name AS TableName 
    , s.name AS IndexName 
    , STATS_DATE(s.id,s.indid) AS 'Statistics Last Updated' 
    , s.rowcnt AS 'Row Count' 
    , s.rowmodctr AS 'Number Of Changes' 
    , CAST((CAST(s.rowmodctr AS DECIMAL(28,8))/CAST(s.rowcnt AS 
DECIMAL(28,2)) * 100.0) 
                             AS DECIMAL(28,2)) AS '% Rows Changed' 
FROM sys.sysindexes s 
INNER JOIN sys.tables st ON st.[object_id] = s.[id] 
INNER JOIN sys.schemas ss ON ss.[schema_id] = st.[schema_id] 
WHERE s.id > 100 
  AND s.indid > 0 
  AND s.rowcnt >= 500 
ORDER BY SchemaName, TableName, IndexName

结果如下:

因为查询计划是根据统计信息来的,索引的选择同样取决于统计信息,所以根据统计信息更新的多寡可以看出数据库的大体状况,20%的自动更新对于大表来说非常慢。

有关索引的DMV的更多相关文章

  1. c#Winform程序调用app.config文件配置数据库连接字符串 SQL Server文章目录 浅谈SQL Server中统计对于查询的影响 有关索引的DMV SQL Server中的执行引擎入门 【译】表变量和临时表的比较 对于表列数据类型选择的一点思考 SQL Server复制入门(一)----复制简介 操作系统中的进程与线程

    c#Winform程序调用app.config文件配置数据库连接字符串 你新建winform项目的时候,会有一个app.config的配置文件,写在里面的<connectionStrings n ...

  2. 有关索引的DMV(转)

    转自:http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html 1.查看那些被大量更新,却很少被使用的索引 SET TRANSAC ...

  3. SQL Server 索引知识-应用,维护

    创建聚集索引 a索引键最好唯一(如果不唯一会隐形建立uniquier列(4字节)确保唯一,也就是这列都会复制到所有非聚集索引中) b聚集索引列所占空间应尽量小(否则也会使非聚集索引的空间变大) c聚集 ...

  4. EF+MVC+cod First项目性能优化总结

    1.EF:this.Configuration.UseDatabaseNullSemantics = true; //关闭数据库null比较行为 2.实体必填字段要加:[Required]属性,可定长 ...

  5. SQL Server学习路径(文章目录)

    SQL Server文章目录 SQL Server文章目录(学习路径)  转自:http://www.cnblogs.com/CareySon/archive/2012/05/08/2489748.h ...

  6. SQL Server数据库的软硬件性能瓶颈

    在过去十年里,很多复杂的企业应用都是用Microsoft SQL Server进行开发和部署的.如今,SQL Server已经成为现代业务应用的基石,并且它还是很多大公司业务流程的核心.SQL Ser ...

  7. 第七章——DMVs和DMFs(2)——用DMV和DMF监控索引性能

    原文:第七章--DMVs和DMFs(2)--用DMV和DMF监控索引性能 本文继续介绍使用DMO来监控,这次讲述的是监控索引性能.索引是提高查询性能的关键性手段.即使你的表上有合适的索引,你也要时时刻 ...

  8. 译:Missing index DMV的 bug可能会使你失去理智---慎重看待缺失索引DMV中的信息

    注: 本文译自https://www.sqlskills.com/blogs/paul/missing-index-dmvs-bug-that-could-cost-your-sanity/ 原文作者 ...

  9. 译:SQL Server的Missing index DMV的 bug可能会使你失去理智---慎重看待缺失索引DMV中的信息

    注: 本文译自https://www.sqlskills.com/blogs/paul/missing-index-dmvs-bug-that-could-cost-your-sanity/ 原文作者 ...

随机推荐

  1. .NET框架源码解读之准备CLR源码阅读环境

    微软发布了CLR 2.0的源码,这个源码是可以直接在freebsd和windows环境下编译及运行的,请在微软shared source cli(http://www.microsoft.com/en ...

  2. Mathout In Action(中文)

    http://download.csdn.net/detail/zxnm55/5593881

  3. C#设计模式(23种模式)

    https://www.cnblogs.com/abcdwxc/archive/2007/10/30/942834.html

  4. 遍历datatable的几种方法(C# )

    转载 遍历datatable的方法2009-09-08 10:02方法一:      DataTable dt = dataSet.Tables[0];      for(int i = 0 ; i  ...

  5. 重新打造的我的Pugo

    Pugo博客已经搭建了好几个月了吧,给我感受到非常方便的就是,我换了好多VPS,迁移显得非常的方便,但是也有不足的地方,比如发布一篇新的博客,我每次都需要重新进入后台进行新的Post,还需要重新bui ...

  6. C#中Cookies的读取

    C#中Cookies的读取   链接: 一 .写入Cookie 1. Name 和 Value 属性由程序设定,默认值都是空引用. 2. Domain属性的默认值为当前URL的域名部分,不管发出这个c ...

  7. django系列6--Ajax04 请求设置(设置csrf_token)

    Ajax请求设置csrf_token 官方文档 csrf_token: https://docs.djangoproject.com/en/1.11/ref/csrf/ CSRF 跨站请求攻击,简单地 ...

  8. WIN7 64位配置X86 MySQL 数据源

    在运行中输入“c:\windows\syswow64\odbcad32.exe”,在调出来的ODBC管理器中配置数据源.

  9. “全栈2019”Java第一百零一章:局部内部类覆盖作用域内成员详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  10. 总结day2 ---- while循环的简单使用, 格式化输出.运算符.以及编码的应用

    内容提要 一 : while 循环 while 的基本语句操作 如何终止循环 二 :格式化输出 三 :运算符号 四 :编码初识别 一 : while 循环 1  >>>>whi ...