【SqlServer】統計索引使用情況解決DB的CPU高和IO高的問題
檢視索引情況
sp_helpindex 表名;
顯示索引使用情況
user_seeks和user_scans欄位都為0的,考慮是否為垃圾索引
另外last_user_seek,last_user_scan如果是一個很早的時間,則考慮是否應用變化
導致該索引不被使用了
SELECT i.name indexname,user_seeks,user_scans,last_user_seek,last_user_scan 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 database_id = db_id('ClntMgr') AND s.object_id = object_id('IDVerifyTbl');
返回指定資料庫、表、索引的碎片
對於索引型別為HEAP,一般情況下碎片比例會較大
原因:
- 1.沒有聚集索引的表稱為堆,意思是其中儲存的資料沒有特定的順序。
- 2.在索引重建或者重新組織時,聚集索引依照聚集鍵和它重排序的資料頁進行排序。
- 3.但是堆不會在索引重建或重新組織期間被重新生成,所以會脫離控制的增長,佔用的資料頁比必要的多很多。
SELECT OBJECT_NAME(f.object_id) 表名, i.name 索引名,f.index_type_desc 索引型別, f.avg_fragmentation_in_percent 碎片比例 FROM sys.dm_db_index_physical_stats(DB_ID('庫名'),OBJECT_ID('表名'),NULL,NULL,'limited') f INNER JOIN sys.indexes i ON i.[object_id] = f.object_id AND i.index_id= f.index_id ORDER BY f.avg_fragmentation_in_percent DESC;
線上重新生成表的所有索引
ALTER INDEX ALL ON 庫名.dbo.表名 REBUILD WITH (ONLINE = ON);
重新組織表的所有索引
ALTER INDEX all ON 庫名.dbo.表名 REORGANIZE;
查看錶、索引佔用磁碟空間情況
SELECT name '表名', convert (char(11), row_Count) as '資料條數', (reservedpages * 8) '已用空間(KB)', (pages * 8) '資料佔用空間(KB)', (CASE WHEN usedpages > pages THEN (usedpages - pages) ELSE 0 END) * 8 '索引佔用空間(KB)', (CASE WHEN reservedpages > usedpages THEN (reservedpages - usedpages) ELSE 0 END) * 8 '未用空間(KB)', LTRIM (STR (reservedpages * 8/1024/1024, 15, 0) + ' GB') as '已用空間(GB)' from( SELECT name,SUM (reserved_page_count) as reservedpages , SUM (used_page_count) as usedpages , SUM ( CASE WHEN (index_id < 2) THEN (in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count) ELSE lob_used_page_count + row_overflow_used_page_count END ) as pages, SUM ( CASE WHEN (index_id < 2) THEN row_count ELSE 0 END )as row_Count FROM sys.dm_db_partition_stats inner join sys.objects on sys.dm_db_partition_stats.object_id=sys.objects.object_id where type='U' group by sys.objects.name union SELECT sys.objects.name, sum(reserved_page_count) as reservedpages, sum(used_page_count) as usedpages, 0 as pages, 0 as row_count from sys.objects inner join sys.internal_tables on sys.objects.object_id = sys.internal_tables.parent_id inner join sys.dm_db_partition_stats on sys.dm_db_partition_stats.object_id=sys.internal_tables.object_id where sys.internal_tables.internal_type IN (202,204,211,212,213,214,215,216) group by sys.objects.name) t order by '已用空間(KB)' desc
查看錶缺失的索引資訊
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 [Number Indexes Missing] DESC;
確定開銷最高的缺失索引
column_usage的取值有如下幾種情況:
- 1.EqualityUsage代表在該列上做了相等運算;
- 2.InequalityUsage代表在該列上做了不等運算;
- 3.Include Cloumns代表包含性列
- 此查詢的結果(按"總開銷"排序)顯示最重要缺失索引的成本以及有關資料庫/架構/表和缺失索引中所需列的資訊。特別是,此指令碼可確定哪些列在相等和不相等 SQL 語句中使用。另外,它還報告應將哪些其他列用作缺失索引中的包含性列。
使用包含性列可以在不從基礎頁獲取資料的情況下滿足更多的覆蓋查詢,因而使用的 I/O 操作更少,從而提高效能。
SELECT TOP 100 [Total Cost] = ROUND(avg_total_user_cost * avg_user_impact * (user_seeks + user_scans),0) , avg_user_impact , 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;