禁用所有非聚集索引

时间:2010-03-25 17:58:01

标签: sql-server tsql sql-server-2008 indexing

我使用以下内容从我的数据库中选择了许多非聚集索引:

SELECT  sys.objects.name tableName,
        sys.indexes.name indexName
FROM    sys.indexes
        JOIN sys.objects ON sys.indexes.object_id = sys.objects.object_id
WHERE   sys.indexes.type_desc = 'NONCLUSTERED'
        AND sys.objects.type_desc = 'USER_TABLE'

我想在每个结果上运行以下内容:

ALTER INDEX indexName ON tableName DISABLE

我该怎么做呢?还有更好的方法吗?

修改

我这样做是为了截断表,然后用“ALTER INDEX bla ON table REBUILD”重建。这需要自动化,因此丢弃和重建将是一个更高的维护活动,我宁愿避免。这是一个糟糕的计划吗?我需要一种以最小的开销清空表的方法。

5 个答案:

答案 0 :(得分:31)

您可以将查询构建到select语句中,如下所示:

DECLARE @sql AS VARCHAR(MAX)='';

SELECT @sql = @sql + 
'ALTER INDEX ' + sys.indexes.name + ' ON  ' + sys.objects.name + ' DISABLE;' +CHAR(13)+CHAR(10)
FROM 
    sys.indexes
JOIN 
    sys.objects 
    ON sys.indexes.object_id = sys.objects.object_id
WHERE sys.indexes.type_desc = 'NONCLUSTERED'
  AND sys.objects.type_desc = 'USER_TABLE';

EXEC(@sql);

第13章和第10章是换行/回车,因此您可以将EXEC替换为PRINT来检查输出,并且它更具可读性。

答案 1 :(得分:3)

使用索引和表名构建表变量。使用循环迭代它们,并为每个循环执行动态SQL语句。

declare @Indexes table
(
    Num       int identity(1,1) primary key clustered,
    TableName nvarchar(255),
    IndexName nvarchar(255)
)

INSERT INTO @Indexes
(
    TableName,
    IndexName
)
SELECT  sys.objects.name tableName,
        sys.indexes.name indexName
FROM    sys.indexes
        JOIN sys.objects ON sys.indexes.object_id = sys.objects.object_id
WHERE   sys.indexes.type_desc = 'NONCLUSTERED'
        AND sys.objects.type_desc = 'USER_TABLE'

DECLARE @Max INT
SET @Max = @@ROWCOUNT

SELECT @Max as 'max'
SELECT * FROM @Indexes

DECLARE @I INT
SET @I = 1

DECLARE @TblName NVARCHAR(255), @IdxName NVARCHAR(255)

DECLARE @SQL NVARCHAR(MAX)

WHILE @I <= @Max
BEGIN
    SELECT @TblName = TableName, @IdxName = IndexName FROM @Indexes WHERE Num = @I
    SELECT @SQL = N'ALTER INDEX ' + @IdxName + N' ON ' + @TblName + ' DISABLE;'

    EXEC sp_sqlexec @SQL    

    SET @I = @I + 1

END

答案 2 :(得分:0)

OTOH它可能更好DROP而不是DISABLE(或者它是Oracle和MS SQL之间的小小的语法差异?:-)我提到的原因是我记得每天重复填充和重复规范化的表格,并且我们正在删除所有索引,以便在我们加载新日期并重建所有索引后强制DB重建索引和sproc执行计划。

当然我们有单独的脚本,因为一旦删除它们,索引就不再存在于系统表中。

答案 3 :(得分:0)

使用游标编写脚本比临时表更简洁(并且稍微简短)。要重新启用索引,请将DISABLE替换为REBUILD。

DECLARE cur_indexes CURSOR FOR
SELECT  sys.objects.name tableName,
        sys.indexes.name indexName
FROM    sys.indexes
        JOIN sys.objects ON sys.indexes.object_id = sys.objects.object_id
WHERE   sys.indexes.type_desc = 'NONCLUSTERED'
        AND sys.objects.type_desc = 'USER_TABLE'

DECLARE @TblName NVARCHAR(255), @IdxName NVARCHAR(255)

DECLARE @SQL NVARCHAR(MAX)

open cur_indexes
fetch next from cur_indexes into @TblName, @IdxName

WHILE @@FETCH_STATUS = 0
BEGIN
    SELECT @SQL = N'ALTER INDEX ' + @IdxName + N' ON ' + @TblName + ' DISABLE;'

    EXEC sp_sqlexec @SQL    

    fetch next from cur_indexes into @TblName, @IdxName
END

close cur_indexes
deallocate cur_indexes

答案 4 :(得分:0)

仅禁用唯一的非聚集索引

DECLARE @EnableOrRebuild as nvarchar(20)
SET @EnableOrRebuild = 'DISABLE'
/* SET @EnableOrRebuild = 'REBUILD' */ -- Uncomment for REBUILD
DECLARE @TableName as nvarchar(200) = 'ChorusDestinataire' -- Enter your table name here
DECLARE @SchemaName as nvarchar(200) = 'dbo' -- Enter the schema here
DECLARE @Sql as nvarchar(2000)=''

SELECT @Sql = @Sql + N'ALTER INDEX ' + quotename(i.name) + N' ON ' + quotename(s.name) + '.' + quotename(o.name) + ' ' + @EnableOrRebuild + N';' + CHAR(13) + CHAR(10)
  FROM sys.indexes i
 INNER JOIN sys.objects o ON i.object_id = o.object_id
 INNER JOIN sys.schemas s ON s.schema_id = o.schema_id
 WHERE i.type_desc = N'NONCLUSTERED'
   AND i.ignore_dup_key = 1
   AND o.type_desc = N'USER_TABLE'
   AND o.name = @TableName 
   AND s.name = @SchemaName

 -- SELECT @Sql;
EXEC (@Sql);