查询索引中的碎片和重建SQL server索引
无论何时对基础数据执行插入、更新或删除操作,SQL Server 数据库引擎都会自动维护索引。随着时间的推移,这些修改可能会导致索引中的信息分散在数据库中(含有碎片)。当索引包含的页中的逻辑排序(基于键值)与数据文件中的物理排序不匹配时,就存在碎片。碎片非常多的索引可能会降低查询性能,导致应用程序响应缓慢。下面是一些简单的查询索引的sql。MSSQL的 DBA_Huangzj 提供。
判断无用的索引:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 30 DB_NAME() AS DatabaseName , '[' + SCHEMA_NAME(o.Schema_ID) + ']' + '.' + '[' + OBJECT_NAME(s.[object_id]) + ']' AS TableName , i.name AS IndexName , i.type AS IndexType , 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
判断 哪些索引缺失:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 30 ROUND(s.avg_total_user_cost * s.avg_user_impact * ( s.user_seeks + s.user_scans ), 0) AS [Total Cost] , s.avg_total_user_cost * ( s.avg_user_impact / 100.0 ) * ( s.user_seeks + s.user_scans ) AS Improvement_Measure , DB_NAME() AS DatabaseName , d.[statement] AS [Table Name] , equality_columns , inequality_columns , 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 WHERE s.avg_total_user_cost * ( s.avg_user_impact / 100.0 ) * ( s.user_seeks + s.user_scans ) > 10 ORDER BY [Total Cost] DESC , s.avg_total_user_cost * s.avg_user_impact * ( s.user_seeks + s.user_scans ) DESC
看看那些索引维护成本很高 通俗的说就是更新次数大于使用这个索引的次数
SELECT TOP 20 DB_NAME() AS DatabaseName , '[' + SCHEMA_NAME(o.Schema_ID) + ']' + '.' + '[' + OBJECT_NAME(s.[object_id]) + ']' AS TableName , i.name AS IndexName , i.type AS IndexType , ( 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('{0}') 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
常常使用的索引查看 看看你常用使用的索引是否建立的合理
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 DB_NAME() AS DatabaseName , '['+SCHEMA_NAME(o.Schema_ID)+']'+'.'+'['+OBJECT_NAME(s.[object_id]) +']'AS TableName , i.name AS IndexName , i.type as IndexType , (s.user_seeks + s.user_scans + s.user_lookups) AS Usage , s.user_updates 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
决定使用哪种碎片整理方法的第一步是分析索引以确定碎片程度 DBCC SHOWCONTIG(表名) WITH ALL_INDEXES 先查碎片信息。
重新组织:
若要重新组织一个或多个索引,可以使用带 REORGANIZE 子句的 ALTER INDEX 语句。此语句可以替代 DBCC INDEXDEFRAG 语句。若要重新组织已分区索引的单个分区,可以使用 ALTER INDEX 的 PARTITION 子句。
重新组织索引是通过对叶页进行物理重新排序,使其与叶节点的逻辑顺序(从左到右)相匹配,从而对表或视图的聚集索引和非聚集索引的叶级别进行碎片整理。使页有序可以提高索引扫描的性能。索引在分配给它的现有页内重新组织,而不会分配新页。如果索引跨多个文件,将一次重新组织一个文件,不会在文件之间迁移页。
重新组织还会压缩索引页。如果还有可用的磁盘空间,将删除此压缩过程中生成的所有空页。压缩基于 sys.indexes 目录视图中的填充因子值。
重新组织进程使用最少的系统资源。而且,重新组织是自动联机执行的。该进程不持有长期阻塞锁,所以不会阻止运行查询或更新。
索引碎片不太多时,可以重新组织索引。请参阅上面的表,了解有关碎片的指导原则。不过,如果索引碎片非常多,重新生成索引则可以获得更好的结果。
重新组织索引时,除了重新组织一个或多个索引外,默认情况下还将压缩聚集索引或基础表中包含的大型对象数据类型 (LOB)。数据类型 image、text、ntext、varchar(max)、nvarchar(max)、varbinary(max) 和 xml 都是大型对象数据类型。压缩此数据可以改善磁盘空间使用情况:
-
重新组织指定的聚集索引将压缩该聚集索引的叶级别(数据行)包含的所有 LOB 列。
-
重新组织非聚集索引将压缩该索引中属于非键(包含性)列的所有 LOB 列。
-
如果指定 ALL,将重新组织与指定的表或视图相关联的所有索引,并压缩与聚集索引、基础表或带有包含列的非聚集索引相关联的所有 LOB 列。
-
如果 LOB 列不存在,则忽略 LOB_COMPACTION 子句。
重新生成:
重新生成索引将删除该索引并创建一个新索引。此过程中将删除碎片,通过使用指定的或现有的填充因子设置压缩页来回收磁盘空间,并在连续页中对索引行重新排序(根据需要分配新页)。这样可以减少获取所请求数据所需的页读取数,从而提高磁盘性能。
可以使用下列方法重新生成聚集索引和非聚集索引:
-
带 REBUILD 子句的 ALTER INDEX。此语句将替换 DBCC DBREINDEX 语句。
-
带 DROP_EXISTING 子句的 CREATE INDEX。
重新组织或重新生成索引
-
在“对象资源管理器”中,展开包含您要重新组织索引的表的数据库。
-
展开“表”文件夹。
-
展开要为其重新组织索引的表。
-
展开“索引”文件夹。
-
右键单击要重新组织的索引,然后选择“重新组织”。
-
在“重新组织索引”对话框中,确认正确的索引位于“要重新组织的索引”网格中,然后单击“确定”。
-
选中“压缩大型对象列数据”复选框,以指定也压缩所有包含大型对象 (LOB) 数据的页。
-
单击“确定”。
重新组织表中的所有索引
-
在“对象资源管理器”中,展开包含您要重新组织索引的表的数据库。
-
展开“表”文件夹。
-
展开要为其重新组织索引的表。
-
右键单击“索引”文件夹,然后选择“全部重新组织”。
-
在“重新组织索引”对话框中,确认正确的索引位于“要重新组织的索引”中。 若要从“要重新组织的索引”网格中删除索引,请选择该索引,再按 Delete 键。
-
选中“压缩大型对象列数据”复选框,以指定也压缩所有包含大型对象 (LOB) 数据的页。
-
单击“确定”。
重新生成索引
-
在“对象资源管理器”中,展开包含您要重新组织索引的表的数据库。
-
展开“表”文件夹。
-
展开要为其重新组织索引的表。
-
展开“索引”文件夹。
-
右键单击要重新组织的索引,然后选择“重新组织”。
-
在“重新生成索引”对话框中,确认正确的索引位于“要重新生成的索引”网格中,然后单击“确定”。
-
选中“压缩大型对象列数据”复选框,以指定也压缩所有包含大型对象 (LOB) 数据的页。
-
单击“确定”。