打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
SQL Server 索引优化

我们知道,合理的索引能大幅提升性能,但冗余的索引也会降低数据库性能。随着我们业务的发展,数据库的中的表、表结构、查询的内容都有可能发生变化。这样,有的索引就可能不再使用了,需要删除(因为维护索引即浪费存储,又耗费性能);而有的表则需要修改或者增加索引。本文主要给出快速确定不再使用的索引的查找方式之一,动态视图(DMV)查询。

无用索引

首先我们来看一下如何查询无用的索引。sys.dm_db_index_usage_stats 记录自上次重启或数据库离线或重置统计信息后使用到的索引,sys.indexes 记录数据中所有表的索引,排除掉最近使用的索引,即为最近没有使用的索引,具体脚本如下:

  1. --查询数据库中没有使用过到索引
  2. USE WideWorldImporters;
  3. GO
  4. DECLARE @dbid INT=DB_ID('WideWorldImporters');
  5. WITH cte AS(
  6. SELECT
  7. [object_id],index_id
  8. FROM sys.indexes
  9. EXCEPT
  10. SELECT
  11. [object_id],index_id
  12. FROM sys.dm_db_index_usage_stats
  13. WHERE database_id=@dbid)
  14. SELECT
  15. o.name tableName,i.name indexName
  16. FROM sys.indexes i
  17. INNER JOIN cte ON cte.index_id=i.index_id AND cte.[object_id]=i.[object_id]
  18. INNER JOIN sys.objects o ON i.[object_id]=o.[object_id]
  19. WHERE o.[type] IN ('U','V') AND i.[type]>0;

因为我们只考察用户创建的表或者索引视图,最后我们只筛选出sys.objects 中type为“U”(用户创建的表)和“V”(用户创建的视图索引)。sys.indexes 中type=0是堆,所以也排除。下面给出产生删除索引的脚本:

 

  1. --删除没有使用过索引脚本产生
  2. USE WideWorldImporters;
  3. GO
  4. DECLARE @dbid INT=DB_ID('WideWorldImporters');
  5. WITH cte AS(
  6. SELECT
  7. [object_id],index_id
  8. FROM sys.indexes
  9. EXCEPT
  10. SELECT
  11. [object_id],index_id
  12. FROM sys.dm_db_index_usage_stats
  13. WHERE database_id=@dbid)
  14. SELECT
  15. 'DROP INDEX '+i.name+' ON '+ o.name
  16. FROM sys.indexes i
  17. INNER JOIN cte ON cte.index_id=i.index_id AND cte.[object_id]=i.[object_id]
  18. INNER JOIN sys.objects o ON i.[object_id]=o.[object_id]
  19. WHERE o.[type] IN ('U','V') AND i.[type]>0;

上面的脚本每条对应一个表的一个索引的删除语句,当然也可以使用如下脚本产生一条语句。

  1. DECLARE @dbid INT=DB_ID('WideWorldImporters');
  2. declare @sql varchar(max);
  3. WITH cte AS(
  4. SELECT
  5. [object_id],index_id
  6. FROM sys.indexes
  7. EXCEPT
  8. SELECT
  9. [object_id],index_id
  10. FROM sys.dm_db_index_usage_stats
  11. WHERE database_id=@dbid)
  12. SELECT @sql=(
  13. SELECT
  14. 'drop index '+i.name+' on '+ o.name
  15. FROM sys.indexes i
  16. INNER JOIN cte ON cte.index_id=i.index_id AND cte.[object_id]=i.[object_id]
  17. INNER JOIN sys.objects o ON i.[object_id]=o.[object_id]
  18. WHERE o.[type] IN ('U','V') AND i.[type]>0
  19. FOR XML PATH(''),type).value('.','NVARCHAR(MAX)');
  20. --exec sp_executesql @sql

细心的读者会发现,上面最后一条语句(exec sp_executesql @sql)是注释掉的,直接这样执行是可以最快速的删除所有无用索引。但是,正如我们上面所说的,sys.dm_db_index_usage_stats 记录自上次重启或数据库离线或重置统计信息后使用到的索引,所以其记录的用到的索引可能是不全的(如果我们最近刚重启过数据库服务、数据库所在的服务器或者重置了动态视图),这样可能导致部分有用的索引也被删除掉,切记、切记、切记,生成的脚本不能直接执行。保险的做法是,至少,在数据库服务运行一个月做这样的事情,如果有经常重启维护的数据库服务,可以在数据库重启维护之前收集记录已经使用的索引。经过几个月或一年的记录,最终确定不需要的索引,再进行删除。

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
查看SQLServer索引的使用情况
Sql Server 揭开隐藏数据的面纱,优化应用程序性能
cnblogs: 数据库性能优化:SQL索引 – 伊凡 易站|工作室 | 易站|工作室
sys.sysobjects、sys.all
聊一聊数据库中的锁
SQL Server维护数据库
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服