Sql Server無用索引查詢

首先我們來看一下如何查詢無用的索引。sys.dm_db_index_usage_stats 記錄自上次重啓或數據庫離線或重置統計信息後使用到的索引,sys.indexes 記錄數據中所有表的索引,排除掉最近使用的索引,即爲最近沒有使用的索引,具體腳本如下:

--查詢數據庫中沒有使用過的索引
USE WideWorldImporters;
GO
DECLARE @dbid INT=DB_ID('WideWorldImporters');
WITH cte AS(
SELECT
[object_id],index_id
FROM sys.indexes
EXCEPT
SELECT
[object_id],index_id
FROM sys.dm_db_index_usage_stats
WHERE database_id=@dbid)
SELECT
o.name tableName,i.name indexName
FROM sys.indexes i
INNER JOIN cte ON cte.index_id=i.index_id AND cte.[object_id]=i.[object_id]
INNER JOIN sys.objects o ON i.[object_id]=o.[object_id]
WHERE o.[typeIN ('U','V'AND i.[type]>1 AND is_primary_key=0 ;
 

因爲我們只考察用戶創建的表或者索引視圖,最後我們只篩選出sys.objects 中type爲“U”(用戶創建的表)和“V”(用戶創建的視圖索引)。sys.indexes 中type=0是堆,type=1是聚集索引,所以也排除,同時我們排除主鍵索引。下面給出生成刪除索引的腳本:

DECLARE @dbid INT=DB_ID('WideWorldImporters');
WITH cte AS(
SELECT
[object_id],index_id
FROM sys.indexes
EXCEPT
SELECT
[object_id],index_id
FROM sys.dm_db_index_usage_stats
WHERE database_id=@dbid)
SELECT
'DROP INDEX '+i.name+' ON '+ o.name
FROM sys.indexes i
INNER JOIN cte ON cte.index_id=i.index_id AND cte.[object_id]=i.[object_id]
INNER JOIN sys.objects o ON i.[object_id]=o.[object_id]
WHERE o.[type] IN ('U','V') AND i.[type]>1 AND is_primary_key=0;
 

上面的腳本每條對應一個表的一個索引的刪除語句,當然也可以使用如下腳本產生一條語句。

DECLARE @dbid INT=DB_ID('WideWorldImporters');
DECLARE @sql VARCHAR(MAX);
WITH cte AS(
SELECT
[object_id],index_id
FROM sys.indexes
EXCEPT
SELECT
[object_id],index_id
FROM sys.dm_db_index_usage_stats
WHERE database_id=@dbid)
SELECT @sql=(
SELECT
            'DROP INDEX '+i.name+' ON '+ o.name   + CHAR(10)-- CHAR(10) 換行
FROM sys.indexes i
INNER JOIN cte ON cte.index_id=i.index_id AND cte.[object_id]=i.[object_id]
INNER JOIN sys.objects o ON i.[object_id]=o.[object_id]
WHERE o.[type] IN ('U','V') AND i.[type]>1 AND is_primary_key=0
FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)');
--exec sp_executesql @sql
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章