SQL Server 重建索引 - 脚本

3

我正在使用@Namphibian的脚本,但是我在那里遇到了一些问题。

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

我使用“详细”而不是“抽样”,但仍有一些索引未被重建。我发现了一些碎片化值超过30%的索引,但仍未被重建或重新组织。该脚本已经连续运行了4天每晚运行。我的问题是我无法使用维护计划来完成这个任务。

请问有什么想法吗?


可能是因为表太小了,请检查这些索引的 s.page_count。 - Denis Rubashkin
你尝试手动重建其中一个索引了吗?这是否会导致与脚本不同的结果? - Tyron78
不要重复发明轮子,看一下 [Ola Hallengren 的维护解决方案] (https://ola.hallengren.com/)。这在 SQL Server 社区中备受推崇,并广泛用于数据库维护。 - Dan Guzman
现在我正在查看未重建索引的数量,大约有一百个。我知道这是一个有很多索引的巨大数据库。@Tyron78 我会尝试重建一些索引,这是一个好主意,谢谢。明天我会在这里发布结果。 @DanGuzman 谢谢Dan,但对我来说太复杂了,我不擅长阅读脚本,找到那里的东西,就像我说的那样,对我来说太复杂了:( 我只需要简单的东西,从一个特定的数据库中获取我的索引,并确定哪一个超过30%,然后重建它们。 - Roman Schmidt
@RomaneS,你还在遇到这个问题吗?当你像tyron78说的那样手动重建其中一个索引时会发生什么? - polzka90
1个回答

1
根据这个答案: https://dba.stackexchange.com/questions/18372/why-index-rebuild-does-not-reduce-index-fragmentatation 你需要考虑索引的页数来确定是否需要重建索引。 我建议将你的INSERT INTO SELECT更改为以下内容。
    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%],
    page_count
FROM 
    sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL, 'DETAILED') 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
    AND s.avg_fragmentation_in_percent > 0
    AND page_count > 1000

嗨@polzka90,当我尝试更改那些行时,它最终出现了以下错误:Msg 213,级别16,状态1,第11行 提供的值的列名或编号与表定义不匹配。有什么建议吗?:( - Roman Schmidt
抱歉耽误了,你能提供一些链接让我查看所有新的查询吗?我测试过它并且它有效。 - polzka90

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接