如何快速检测和解决数据库的SQL Server索引碎片?

Tom*_*ott 4 sql sql-server fragmentation database-indexes azure-sql-database

我遇到过这样一种情况:随着更多记录的添加,我对许多SQL Server数据库表的数据库操作变得非常缓慢(单个插入到具有100万条记录的表的5s).

我估计这可能是由于我的数据库中表的碎片索引,因为我有许多表使用(并且需要使用)主键聚簇索引的uniqueidentifier类型.

我如何评估是否是这种情况,如果存在任何碎片问题,如何解决碎片问题(可能每次部署一次)?

我想要一个适用于SQL Server 2005及更高版本的解决方案(我在Azure数据库(12.0.2000.8)中专门使用SQL Server).

Aru*_*ngh 6

检查表上的碎片百分比

SELECT a.index_id, 
       NAME, 
       avg_fragmentation_in_percent, 
       fragment_count, 
       avg_fragment_size_in_pages 
FROM   sys.Dm_db_index_physical_stats(Db_id('dbName'), Object_id('tableName'), 
       NULL, 
              NULL, NULL) AS a 
       INNER JOIN sys.indexes b 
               ON a.object_id = b.object_id 
                  AND a.index_id = b.index_id 
Run Code Online (Sandbox Code Playgroud)

要修复碎片,请重建或重新组织表上的索引

ALTER INDEX ALL ON table_name REBUILD 
Run Code Online (Sandbox Code Playgroud)

要么

ALTER INDEX index_name ON table_name REBUILD 
Run Code Online (Sandbox Code Playgroud)

- 重组

ALTER INDEX ALL ON table_name REORGANIZE
Run Code Online (Sandbox Code Playgroud)

要么

ALTER INDEX index_name ON table_name REORGANIZE
Run Code Online (Sandbox Code Playgroud)

要么

DBCC DBREINDEX ('table_Name')
Run Code Online (Sandbox Code Playgroud)

https://docs.microsoft.com/en-us/sql/relational-databases/indexes/reorganize-and-rebuild-indexes


Tom*_*ott 4

这是一个适用于 SQL Server 2005 及更高版本的 SQL 查询解决方案,它可以让您

1)首先找到所有需要重建或重组的索引以减少碎片,然后

2) 将结果的前五列复制粘贴到新的查询窗口(删除列标题行),执行所有语句(重建/重新组织索引),这将解决当前大多数碎片问题在数据库中的所有表中。

注意:如果遇到权限错误,您可能需要确保您位于主模式中,并且您的用户对数据库具有适当的权限。

我将此查询命名为:GetFragmentationOfIndexesAndFirst5ColumnsExecutedResolveFragmentation.sql

SELECT  
'alter index' as 'reindex_part1',
'[' + dbindexes.[name] + ']' as 'Index',
'on' as 'reindex_part2',
'[' + dbtables.[name] + ']' as 'Table',
CASE WHEN indexstats.avg_fragmentation_in_percent > 30
 THEN 'rebuild with (FILLFACTOR = 80)' ELSE 'reorganize' END as 'reindex_part3',
indexstats.avg_fragmentation_in_percent,
indexstats.page_count,
indexstats.alloc_unit_type_desc,
dbschemas.[name] as 'Schema'
FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats
INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id]
INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id]
INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id]
AND indexstats.index_id = dbindexes.index_id
WHERE indexstats.database_id = DB_ID()
AND indexstats.avg_fragmentation_in_percent > 5
ORDER BY indexstats.avg_fragmentation_in_percent desc
Run Code Online (Sandbox Code Playgroud)

我必须归功于我在理解并最终得出这个解决方案时使用的两个地方:

在数据库中查找碎片的初始方法: https://myadventuresincoding.wordpress.com/2013/05/27/sql-server-check-index-fragmentation-on-all-indexes-in-a-database/

如何解决数据库内的碎片(5%-30%的碎片应通过重新组织索引来解决,30%以上的碎片应通过重建索引来解决): http ://www.passionforsql.com/how -检查sql-server中的索引碎片/

编辑: 我在上面的查询中包含了该with (FILLFACTOR = 80)部分,因为在我的情况下,大多数碎片索引都位于 uniqueidentifier 列上,不应使用默认的 FILLFACTOR 0 (100%) 对其进行索引,因为这样不可避免地会出现这种情况再次快速导致碎片,因为由于唯一标识符的无序创建,插入总是需要放在其他行之间。您当然可以更改粘贴的值以删除或更改适合您的表/索引的参数。

我还发现您需要EXEC sp_updatestats在重建和重新组织索引后执行,以便统计信息可以赶上索引更改,而不必在将来的查询期间增量执行。