【问题标题】:Best Approach for Reindexing重新索引的最佳方法
【发布时间】:2009-07-13 11:29:25
【问题描述】:

我正在尝试减少在 SQL Server 2005 上运行的数据库的所有索引中的碎片。 目前我正在尝试将 ALTER INDEX 与 sp_MSforeachtable 结合使用,以将其应用于所有表的所有索引:

sp_MSforeachtable "ALTER INDEX ALL ON ? REBUILD;"

但由于某种原因,这似乎并不总是有效? 如果我对单个索引或单个表的所有索引尝试它,那么碎片就会被清除,似乎只是当我将它应用于整个数据库时才会遇到问题。

以前我可能使用过 DBCC DBREINDEX,但 BOL 声明它将在 SQL Server 的下一版本中删除,所以我不想使用它。

谁能给我任何关于清理数据库中所有索引的最佳方法的建议?

谢谢

【问题讨论】:

    标签: sql sql-server database sql-server-2005


    【解决方案1】:

    如果您想完全自动化 SQL Server 索引维护,那么我强烈建议您查看 Michelle Ufford 的存储过程。

    Index Defrag Script V4.1

    这是我认为是我读过的最好的索引维护脚本。

    此脚本的最佳功能之一是您可以自定义您使用的阈值以确定是否重建或重组给定的索引结构。

    它还提供了限制程序使用的 CPU 内核数量的选项。如果您打算在繁忙的实时生产数据库上运行脚本,这是一个很好的选择。

    警告:与所有 Internet 可用代码一样,请务必在生产环境中使用之前对其进行彻底测试。您也很可能还想加入自己的自定义和功能。

    【讨论】:

      【解决方案2】:

      在 SQL Fool(Michelle Ufford 的网站)上查看文章和随附的示例脚本以处理此任务:

      http://sqlfool.com/2009/06/index-defrag-script-v30/

      这是一劳永逸的解决方案!

      最佳实践建议是,如果您有 5-30% 的碎片,则重新组织您的索引,并且仅当它有超过 30% 的碎片时才重建它。您可以轻松使用这些阈值或使用此脚本指定您自己的阈值。

      马克

      【讨论】:

        【解决方案3】:

        或者你可以使用微软的索引重建脚本在这里找到http://msdn.microsoft.com/en-us/library/ms188917.aspx

            -- Ensure a USE <databasename> statement has been executed first.
        SET NOCOUNT ON;
        DECLARE @objectid int;
        DECLARE @indexid int;
        DECLARE @partitioncount bigint;
        DECLARE @schemaname nvarchar(130); 
        DECLARE @objectname nvarchar(130); 
        DECLARE @indexname nvarchar(130); 
        DECLARE @partitionnum bigint;
        DECLARE @partitions bigint;
        DECLARE @frag float;
        DECLARE @command nvarchar(4000); 
        -- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function 
        -- and convert object and index IDs to names.
        SELECT
            object_id AS objectid,
            index_id AS indexid,
            partition_number AS partitionnum,
            avg_fragmentation_in_percent AS frag
        INTO #work_to_do
        FROM sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
        WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;
        
        -- Declare the cursor for the list of partitions to be processed.
        DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;
        
        -- Open the cursor.
        OPEN partitions;
        
        -- Loop through the partitions.
        WHILE (1=1)
            BEGIN;
                FETCH NEXT
                   FROM partitions
                   INTO @objectid, @indexid, @partitionnum, @frag;
                IF @@FETCH_STATUS < 0 BREAK;
                SELECT @objectname = QUOTENAME(o.name), @schemaname = QUOTENAME(s.name)
                FROM sys.objects AS o
                JOIN sys.schemas as s ON s.schema_id = o.schema_id
                WHERE o.object_id = @objectid;
                SELECT @indexname = QUOTENAME(name)
                FROM sys.indexes
                WHERE  object_id = @objectid AND index_id = @indexid;
                SELECT @partitioncount = count (*)
                FROM sys.partitions
                WHERE object_id = @objectid AND index_id = @indexid;
        
        -- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding.
                IF @frag < 30.0
                    SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';
                IF @frag >= 30.0
                    SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';
                IF @partitioncount > 1
                    SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10));
                EXEC (@command);
                PRINT N'Executed: ' + @command;
            END;
        
        -- Close and deallocate the cursor.
        CLOSE partitions;
        DEALLOCATE partitions;
        
        -- Drop the temporary table.
        DROP TABLE #work_to_do;
        GO
        

        我将此脚本与 SQL Server 代理一起使用来自动执行任务。希望这会有所帮助。

        【讨论】:

          【解决方案4】:

          最安全和最便携的方法是删除索引并重新添加它们。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-11-24
            • 2010-11-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-07-10
            相关资源
            最近更新 更多