自动基于碎片化的结果索引重建?(Automate INDEX rebuild based on fr

2019-07-29 07:10发布

是否有可能增加一个维护作业检查索引的碎片。 如果大于50%,则自动重建这些索引?

索引大小可以变化从100MB到10GB。 SQL 2005。

谢谢。

Answer 1:

我使用这个脚本。 请注意,我劝你读了有关我在这里使用他们在SQL2005 +一个隐藏的宝石的DMV。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
CREATE TABLE #FragmentedIndexes
(
 DatabaseName SYSNAME
 , SchemaName SYSNAME
 , TableName SYSNAME
 , IndexName SYSNAME
 , [Fragmentation%] FLOAT
)

INSERT INTO #FragmentedIndexes
SELECT
 DB_NAME(DB_ID()) AS DatabaseName
 , ss.name AS SchemaName
 , OBJECT_NAME (s.object_id) AS TableName
 , i.name AS IndexName
 , s.avg_fragmentation_in_percent AS [Fragmentation%]
FROM sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL, 'SAMPLED') 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 s.object_id = o.object_id
INNER JOIN sys.schemas ss ON ss.[schema_id] = o.[schema_id]
WHERE s.database_id = DB_ID()
AND i.index_id != 0
AND s.record_count > 0
AND o.is_ms_shipped = 0
DECLARE @RebuildIndexesSQL NVARCHAR(MAX)
SET @RebuildIndexesSQL = ''
SELECT
 @RebuildIndexesSQL = @RebuildIndexesSQL +
CASE
 WHEN [Fragmentation%] > 30
   THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
      + QUOTENAME(SchemaName) + '.'
      + QUOTENAME(TableName) + ' REBUILD;'
 WHEN [Fragmentation%] > 10
    THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON '
    + QUOTENAME(SchemaName) + '.'
    + QUOTENAME(TableName) + ' REORGANIZE;'
END
FROM #FragmentedIndexes
WHERE [Fragmentation%] > 10
DECLARE @StartOffset INT
DECLARE @Length INT
SET @StartOffset = 0
SET @Length = 4000
WHILE (@StartOffset < LEN(@RebuildIndexesSQL))
BEGIN
 PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
 SET @StartOffset = @StartOffset + @Length
END
PRINT SUBSTRING(@RebuildIndexesSQL, @StartOffset, @Length)
EXECUTE sp_executesql @RebuildIndexesSQL
DROP TABLE #FragmentedIndexes

也请记住,此脚本可以运行一段时间,并阻止访问你的表。 除非你有Enterprise版本重建索引时,SQL可以锁定表。 直到指数defrag完成使用索引这将阻止所有查询到该表。 因此,不建议仅运行期间的维护窗口期间运行时间索引重建。 如果您正在运行企业版,您可以在线使用ONLINE = ON选项碎片整理的索引。 这将使用更多的空间,但你的表不会被阻塞/磁盘碎片整理操作过程中锁定。

如果您需要了解更多信息呐喊。

更新:

如果你是一个较小的数据库上运行这个查询,你也许可以使用“详细”参数调用sys.dm_db_index_physical_stats。 这可能是指数的更详细的检查。 在评论的讨论也指出,在更大的表,那么很可能是值得做采样扫描,因为这将有助于减少做索引扫描所需要的时间。



Answer 2:

在情况下,你想避免创建任何临时表和解析字符串,创建SQL字符串列表中。 下面是完成它的有效方法:

USE databasename

GO

DECLARE @Queryresult NVARCHAR(4000)

SET @Queryresult=''

SELECT

  @Queryresult=@Queryresult + 'ALTER INDEX ' + QUOTENAME(i.name) + ' ON '
  + QUOTENAME('dbo') + '.'
  + QUOTENAME(OBJECT_NAME(i.OBJECT_ID)) + ' REBUILD;'

 FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'SAMPLED') ss

  INNER JOIN sys.indexes i ON i.OBJECT_ID = ss.OBJECT_ID AND i.index_id = ss.index_id

  INNER JOIN sys.objects o ON ss.object_id = o.object_id

WHERE ss.avg_fragmentation_in_percent > 50

AND ss.record_count > 0 

AND o.is_ms_shipped = 0 --Excludes any objects created as a part of SQL Server installation

AND ss.index_id > 0     --Excludes heap indexes

EXEC sp_executesql @Queryresult


Answer 3:

是的你可以。

您可以使用此查询得到碎片索引:

SELECT OBJECT_NAME(i.OBJECT_ID) AS TableName,
i.name AS IndexName,
indexstats.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') indexstats
INNER JOIN sys.indexes i ON i.OBJECT_ID = indexstats.OBJECT_ID
AND i.index_id = indexstats.index_id
WHERE indexstats.avg_fragmentation_in_percent > 20

并根据其结果只是建立一个命令来重新创建它们

我想在存储过程包一切,从SQL Server作业调用它

仅供参考,50%是一个非常大的碎片。 我会去的少。



Answer 4:

您可以使用sys.dm_db_index_physical_stats来获得有关索引碎片(见avg_fragmentation_in_percent列)的信息。 然后,你可以做,只要达到你的门槛重建子句的ALTER指数。



文章来源: Automate INDEX rebuild based on fragmentation results?