Отключить все некластеризованные индексы
Я выбираю несколько некластеризованных индексов из моей базы данных со следующим:
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". Это должно быть автоматизировано, поэтому отбрасывание и перестройка будут несколько более высокой эксплуатационной активностью, которую я бы предпочел избежать. Это плохой план? Мне нужно средство для опорожнения таблиц с минимальными накладными расходами.
Ответы
Ответ 1
Вы можете создавать запросы в оператор 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
, и это будет более читаемым.
Ответ 2
Создайте переменную таблицы с индексами и именами таблиц. Используйте цикл для итерации по ним и выполните динамический оператор 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
Ответ 3
OTOH, возможно, лучше DROP, а не DISABLE (или это небольшая синтаксическая разница между Oracle и MS SQL?). Причина, по которой я упоминаю, это то, что я помню таблицы, которые были засекречены, а excplicilty денормализованы два раза в день и мы были DROP-ing всех индексов, чтобы заставить DB перестроить как индексы, так и планы выполнения sproc после загрузки новой даты и восстановления всех индексов.
Конечно, для этого у нас был отдельный script, так как после его удаления индексы больше не входят в системные таблицы.
Ответ 4
Использование курсора для script вещей более идиоматично, чем временная таблица (и немного более короткая). Чтобы снова включить индексы, замените 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