【问题标题】:Disable and re-enable all indexes in a SQL Server database禁用和重新启用 SQL Server 数据库中的所有索引
【发布时间】:2013-08-14 15:33:36
【问题描述】:

我正在运行 DTS 以在我的数据库中执行任务,首先我需要禁用数据库中的所有索引,并在 DTS 完成工作后重新启用它们。

有没有办法可以禁用整个数据库中的所有索引,然后再重新启用它们?

我知道如何逐一禁用/启用,有人可以帮助我一次性禁用/启用全部作为 DTS 中的一个步骤。

【问题讨论】:

标签: sql-server sql-server-2005


【解决方案1】:

我们可以使用下面的脚本来禁用索引

ALTER INDEX ALL ON [TableName]
DISABLE;

将您的批量插入到表中,然后在脚本下面运行。

ALTER INDEX ALL ON [TableName]
REBUILD;

【讨论】:

  • 问题为:“禁用并重新启用 SQL Server 数据库中的所有索引”。不是针对单个表,而是针对整个数据库。
  • 哎呀...这是我的错。
  • 这应该是:“ALTER INDEX ALL ON StorageItem REBUILD;”不是“ALTER INDEX ALL ON StorageItem ENABLE;”
  • 它没有完全回答OP的问题,但我喜欢它,它也很有帮助。
  • 这是简单而有效的,但是对于任何到达这个线程想要进行有条件的批量更新或删除的人(比如我),这将禁用你的主键并破坏你的性能。您可能只想禁用非聚集索引,根据您的情况,您最好同时保持一些非聚集索引处于活动状态。
【解决方案2】:

这是一个脚本,它将为数据库中的所有非聚集索引输出 ALTER 语句。您可以轻松修改它以输出 REBUILD 脚本和聚集索引的脚本

select 'ALTER INDEX [' + I.name + '] ON [' + T.name + '] DISABLE' 
from sys.indexes I
inner join sys.tables T on I.object_id = T.object_id
where I.type_desc = 'NONCLUSTERED'
and I.name is not null

【讨论】:

  • 您的意思可能是 REBUILD 而不是 ENABLE?
【解决方案3】:

这适用于 SQL Server 2008 和更新版本。它允许不同的模式以及包含空格、破折号和其他必须引用的特殊字符的名称。 What is the use of the square brackets [] in sql statements?

这些脚本会将代码输出到结果选项卡中。您必须复制/粘贴到查询选项卡中并执行它们。

禁用脚本

SELECT 'ALTER INDEX ' + QUOTENAME(I.name) + ' ON ' +  QUOTENAME(SCHEMA_NAME(T.schema_id))+'.'+ QUOTENAME(T.name) + ' DISABLE' 
FROM sys.indexes I
INNER JOIN sys.tables T ON I.object_id = T.object_id
WHERE I.type_desc = 'NONCLUSTERED'
AND I.name IS NOT NULL
AND I.is_disabled = 0

启用脚本(重建)

SELECT 'ALTER INDEX ' + QUOTENAME(I.name) + ' ON ' +  QUOTENAME(SCHEMA_NAME(T.schema_id))+'.'+ QUOTENAME(T.name) + ' REBUILD' 
FROM sys.indexes I
INNER JOIN sys.tables T ON I.object_id = T.object_id
WHERE I.type_desc = 'NONCLUSTERED'
AND I.name IS NOT NULL
AND I.is_disabled = 1

这是基于此处的另一个答案。

【讨论】:

  • 欣赏添加的 SCHEMA 部分!
【解决方案4】:

为了启用索引,您必须重建它。此脚本将重建所有禁用的索引。

DECLARE @my_sql2 NVARCHAR(200);

DECLARE cur_rebuild CURSOR FOR 
   SELECT 'ALTER INDEX ' +  i.name + ' ON ' + t.name + ' REBUILD' FROM sys.indexes i JOIN sys.tables t ON i.object_id = t.object_id WHERE i.is_disabled = 1 ORDER BY t.name, i.name;
OPEN cur_rebuild;
FETCH NEXT FROM cur_rebuild INTO @my_sql2;
WHILE @@FETCH_STATUS = 0
   BEGIN
      EXECUTE sp_executesql  @my_sql2;
      FETCH NEXT FROM cur_rebuild INTO @my_sql2;
   END;
CLOSE cur_rebuild;
DEALLOCATE cur_rebuild;
GO

【讨论】:

    【解决方案5】:

    在加载大量数据时禁用索引是一个好主意,但是……最大的问题是聚集索引。如果禁用聚集索引,则禁用了整个表。

    有几个选项建议自己,但没有一个是简单的。

    1) 循环遍历系统视图(sys.indexes),提取表和索引名,生成并执行动态SQL来禁用索引。有一个“撤消”例程来重新启用它们。 (小心——它是唯一索引还是唯一约束?)唉,这仅在您不使用聚集索引时才有效。祝你好运。

    2) 与 1 相同,但跳过任何聚集索引。加载数据时,请确保它按(聚集索引)顺序加载,否则加载时间会很短,并且会出现碎片表。 (如果你的数据提供者和我一样,那也祝你好运。)

    3) 在数据库中创建包含“加载”表上的索引定义的表。构建一个循环遍历它们并删除所有索引的例程(最后是聚集索引)。如果您先截断表格,这将很快。加载您的数据,然后循环遍历并从头开始重新创建索引(首先集群)。使用表分区来减少系统其余部分的可怕性(例如,在“加载”表上执行上述所有操作,然后使用分区切换将加载的数据移动到“活动”表中)。我花了很多时间来构建这样一个系统,但它可以而且会起作用。

    【讨论】:

    【解决方案6】:

    使用此脚本禁用所有索引

    -- Disable All Indices
    DECLARE @Script NVARCHAR(MAX)
    DECLARE curIndices CURSOR FAST_FORWARD READ_ONLY FOR
        SELECT 'ALTER INDEX ' + QUOTENAME(indices.name) + ' ON ' + QUOTENAME(SCHEMA_NAME(tableNames.schema_id))+'.'+ QUOTENAME(tableNames.name) + ' DISABLE'
        FROM
            sys.indexes indices  INNER JOIN 
            sys.tables tableNames ON indices.object_id = tableNames.object_id
        WHERE 
            indices.type_desc = 'NONCLUSTERED' AND 
            indices.name IS NOT NULL AND
            indices.is_disabled = 0;
    OPEN curIndices
    FETCH NEXT FROM curIndices INTO @Script
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT @Script
        EXECUTE sp_executesql @Script 
    
        FETCH NEXT FROM curIndices INTO @Script
    END
    CLOSE curIndices
    DEALLOCATE curIndices
    

    使用此脚本重建(启用)所有索引

    -- Rebuild All Indices
    DECLARE @Script NVARCHAR(MAX)
    DECLARE curIndices CURSOR FAST_FORWARD READ_ONLY FOR
        SELECT 'ALTER INDEX ' + QUOTENAME(indices.name) + ' ON ' + QUOTENAME(SCHEMA_NAME(tableNames.schema_id))+'.'+ QUOTENAME(tableNames.name) + ' REBUILD'
        FROM
            sys.indexes indices  INNER JOIN 
            sys.tables tableNames ON indices.object_id = tableNames.object_id
        WHERE 
            indices.type_desc = 'NONCLUSTERED' AND 
            indices.name IS NOT NULL AND
            indices.is_disabled = 1;
    OPEN curIndices
    FETCH NEXT FROM curIndices INTO @Script
    WHILE @@FETCH_STATUS = 0
    BEGIN
        PRINT @Script
        EXECUTE sp_executesql @Script 
    
        FETCH NEXT FROM curIndices INTO @Script
    END
    CLOSE curIndices
    DEALLOCATE curIndices
    

    【讨论】:

      【解决方案7】:

      您必须运行一个脚本来选择表和索引的元数据。然后你可以做一个:

      ALTER INDEX indexname ON tablename DISABLE; 
      

      稍后您可以运行类似的脚本来重建:

      ALTER INDEX indexname ON tablename REBUILD; 
      

      您可以一次执行这些操作,或者将它们收集到 NVARCHAR(MAX) 变量中并作为单个批处理执行。您可以在较早的问题中查看示例代码:

      Disable all non-clustered indexes

      【讨论】:

      • TS 的字面意思是:“我知道如何一个一个地禁用/启用,有人可以帮助我一次禁用/启用所有的方法”
      猜你喜欢
      • 1970-01-01
      • 2013-09-07
      • 2021-11-17
      • 1970-01-01
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-08
      相关资源
      最近更新 更多