2010-03-25 21 views
14

I wybrać liczbę indeksów nieklastrowych z mojej bazy danych z następujących czynności:wyłączyć wszystkie nieklastrowanym indeksy

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' 

Chciałbym uruchomić następujące po sobie wyników:

ALTER INDEX indexName ON tableName DISABLE 

Jak mam to zrobić? Czy istnieje lepszy sposób?

EDIT

Robię to dla celów tabelach obcinania, a następnie odbudowa z "ALTER INDEX REBUILD bla na stole". To musi być zautomatyzowane, więc upuszczenie i przebudowanie byłoby nieco wyższym działaniem konserwacyjnym, którego wolałbym uniknąć. Czy to zły plan? Potrzebuję środków do opróżniania stołów przy minimalnym obciążeniu.

+1

Możecie być lepiej po prostu upuszczając je, ponieważ nie ma ALTER INDEX ENABLE, to oni muszą być odtworzone. Nie będą one utrzymywane, jeśli wyłączone. –

+2

Po upuszczeniu utracisz definicje i będziesz musiał je zapamiętać, jeśli (kiedy) musisz je odtworzyć. Jeśli wyłączone, definicje będą utrwalone w tabelach systemowych i nie musisz się martwić o ponowne tworzenie ich od podstaw. –

+2

@jl możesz ponownie włączyć indeks, używając ALTER INDEX REBUILD. – kristianp

Odpowiedz

24

można budować zapytania w instrukcji wyboru, tak jak poniżej:

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); 

Znaki 13 i 10 to linia-feed/karetki powraca, więc można sprawdzić wyjście zastępując EXEC z PRINT, i będzie bardziej czytelny.

+0

Ale umieść go w jakiejś formie pętli (kursor lub tabelę tymczasową/WHILE konstruuj), aby przetworzyć każdy indeks z kolei –

+0

Dobrze, ale czy wyłączenie indeksów nieklastrowych jest tak drogie, że byłoby to konieczne? –

+1

Powoduje to tylko wyciągnięcie ostatniego wyniku z zestawu. Deklaracja powinna być DECLARE @sql AS VARCHAR (MAX) = ''; i wybierz powinien zaczynać SELECT @sql = @ sql + 'ALTE ... aby połączyć wszystkie wyniki razem. W przeciwnym razie, bardzo miłe. Spróbuję teraz tego. – spender

3

Utwórz zmienną tabeli z indeksami i nazwami tabel. Użyj pętli do iteracji nad nimi i wykonaj dynamiczną instrukcję SQL dla każdego z nich.

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 
0

OTOH może lepiej byłoby DROP raczej wyłączających (czy jest to drobna lil składniowym diff między Oracle i MS SQL? :-) Dlatego wspominam to, że pamiętam tabel, które zostały odbudowane i excplicilty zdenormalizowanych dwa razy dziennie i DROP-owanie wszystkich indeksów, aby zmusić DB do odbudowy indeksów i planów wykonania sproc po załadowaniu nowej daty i odbudowaniu wszystkich indeksów.

Oczywiście mieliśmy oddzielny skrypt do tego, ponieważ po ich upuszczeniu indeksy nie znajdują się już w tabelach systemowych.

+0

Wyłączenie indeksu nieklastrowego zachowuje definicję i pozwala odtworzyć/odbudować o 50% szybciej upuszczanie i tworzenie. – JNK

0

Używanie kursora do skryptowania rzeczy jest bardziej idiomatyczne niż tabelą tymczasową (i nieco krótszą). Aby ponownie włączyć indeksy, zamień DISABLE na 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 
+0

Brakuje ci słowa kluczowego 'CURSOR' w wierszu 1. 'DECLARE cur_indexes CURSOR FOR' – Zack

+0

zaktualizowany, dzięki @Zack – kristianp

Powiązane problemy