用于重建所有表和所有数据库的所有索引的 SQL Server 脚本

发布时间 2023-07-23 21:37:12作者: 雪竹子

问题

DBA 的主要职责之一是维护索引。关于用于索引重建和索引重组的不同命令以及使用 SQL Server 进行索引维护之间的差异,已经写了一些技巧。此外,还编写了有关使用维护计划来维护所有数据库上的索引的其他技巧。维护计划的问题之一是它们似乎并不总是像您希望的那样可靠,并且有时您还会收到关于任务是否实际成功的错误反馈。在本技巧中,我们将介绍一个可用于重建所有数据库的所有索引的简单脚本。

解决方案

维护计划的一个好处是它们可以跨多个数据库工作,因此您可以推出一项任务来处理所有数据库中的相同活动。我发现维护计划的问题是有时它们不能按预期工作,因此在本技巧中我提供了另一种方法。

下面的脚本允许您为所有数据库和数据库中的所有表重建索引。可以进一步调整以仅处理需要基于碎片级别维护的索引,然后进行索引重组或索引重建。

该脚本使用两个游标,一个用于数据库,另一个用于数据库内的表。

为 SQL Server 2005 及更高版本重建所有索引脚本

以下脚本适用于 SQL Server 2005 及更高版本。

因为我们需要从一个数据库切换到另一个数据库,所以我们需要为查询创建动态 SQL 代码。该代码使用 master.sys.databases 来获取数据库列表并检查数据库的状态,以确保我们正在使用在线数据库。这还使用 INFORMATION_SCHEMA.TABLES 来获取数据库中的用户表列表。

DECLARE @Database NVARCHAR(255)   
DECLARE @Table NVARCHAR(255)  
DECLARE @cmd NVARCHAR(1000)  

DECLARE DatabaseCursor CURSOR READ_ONLY FOR  
SELECT name FROM master.sys.databases   
WHERE name NOT IN ('master','msdb','tempdb','model','distribution')  -- databases to exclude
--WHERE name IN ('DB1', 'DB2') -- use this to select specific databases and comment out line above
AND state = 0 -- database is online
AND is_in_standby = 0 -- database is not read only for log shipping
ORDER BY 1  

OPEN DatabaseCursor  

FETCH NEXT FROM DatabaseCursor INTO @Database  
WHILE @@FETCH_STATUS = 0  
BEGIN  

   SET @cmd = 'DECLARE TableCursor CURSOR READ_ONLY FOR SELECT ''['' + table_catalog + ''].['' + table_schema + ''].['' +  
   table_name + '']'' as tableName FROM [' + @Database + '].INFORMATION_SCHEMA.TABLES WHERE table_type = ''BASE TABLE'''   

   -- create table cursor  
   EXEC (@cmd)  
   OPEN TableCursor   

   FETCH NEXT FROM TableCursor INTO @Table   
   WHILE @@FETCH_STATUS = 0   
   BEGIN
      BEGIN TRY   
         SET @cmd = 'ALTER INDEX ALL ON ' + @Table + ' REBUILD' 
         --PRINT @cmd -- uncomment if you want to see commands
         EXEC (@cmd) 
      END TRY
      BEGIN CATCH
         PRINT '---'
         PRINT @cmd
         PRINT ERROR_MESSAGE() 
         PRINT '---'
      END CATCH

      FETCH NEXT FROM TableCursor INTO @Table   
   END   

   CLOSE TableCursor   
   DEALLOCATE TableCursor  

   FETCH NEXT FROM DatabaseCursor INTO @Database  
END  
CLOSE DatabaseCursor   
DEALLOCATE DatabaseCursor

说明

 

我已经排除了系统数据库,因此您可以包含这些数据库或添加其他数据库以从索引维护例程中排除。此外,您还可以更改代码以仅包含特定数据库。

该脚本已经过测试,可与 SQL Server 2005、SQL Server 2008、SQL Server 2008R2、SQL Server 2012、SQL Server 2014、SQL Server 2016、SQL Server 2017 和 SQL Server 2019 配合使用。

后续 

  • 这是一个简单的基本脚本,可以修改为存储过程,还允许您传递其他参数,例如执行索引重建或索引碎片整理。
  • 使用其他选项使索引重建语句更加健壮。
  • 您还可以修改它以从您创建的表中读取数据,以确定要针对哪些数据库和哪些索引运行此操作。可以查看索引碎片情况,只重建需要重建的索引。
  • 此方法会重建所有索引,因此如果您在非常大的索引或大型数据库上运行此方法,请务必小心,因为它需要一些时间才能完成并消耗内存、CPU 和磁盘资源。
  • 看看其他与 索引相关的技巧