2010-03-25 19 views
14

que seleccionar una serie de índices no agrupados de mi base de datos con la siguiente:Desactivar todos los índices no agrupados

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' 

me gustaría ejecutar el siguiente sobre cada uno de los resultados:

ALTER INDEX indexName ON tableName DISABLE 

¿Cómo voy a hacer esto? ¿Hay una mejor manera?

EDITAR

que estoy haciendo esto con el fin de truncar las tablas, a continuación, la reconstrucción con "ALTER bla índice en la tabla RECONSTRUIR". Esto necesita ser automatizado, por lo que descartar y reconstruir sería una actividad de mantenimiento algo mayor que preferiría evitar. ¿Es este un mal plan? Necesito un medio para vaciar mesas con un mínimo de gastos generales.

+1

Es mejor que los dejes caer ya que no hay ALTER INDEX ENABLE, tendrían que ser recreados. No se mantendrán si están deshabilitados. –

+2

Si se descarta, pierde las definiciones y tendrá que recordarlas si (cuando) necesita recrearlas. Si está deshabilitado, las definiciones se mantendrán en las tablas del sistema y no tendrá que preocuparse por volver a crearlas desde cero. –

+2

@jl puede volver a habilitar el índice utilizando ALTER INDEX REBUILD. – kristianp

Respuesta

24

Usted puede construir las consultas en una instrucción de selección, así:

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

Caracteres 13 y 10 son la línea de alimentación/retornos de carro, por lo que puede comprobar la salida mediante la sustitución de EXEC con PRINT, y será más legible.

+0

Pero póngalo en alguna forma de bucle (cursor o tabla temporal/WHILE constructo), para procesar cada índice a su vez –

+0

Buen punto, pero ¿está deshabilitando índices no agrupados tan caros que sería necesario? –

+1

Esto solo saca el último resultado en el conjunto. El declare debe ser DECLARE @sql AS VARCHAR (MAX) = ''; y la selección debería comenzar SELECCIONAR @sql = @ sql + 'ALTE ... para concatenar todos los resultados juntos. De lo contrario, muy agradable. Voy a intentar esto ahora. – spender

3

Cree una variable de tabla con los índices y los nombres de tabla. Use un ciclo para iterar sobre ellos y ejecute una declaración SQL dinámica para cada uno de ellos.

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 tal vez sería mejor a DROP vez que DISABLE (o se trata de un diff sintáctica pequeña lil entre Oracle y MS SQL? :-) La razón que menciono es que recuerdo tablas que fueron repobladas y excplicilty desnormalizado dos veces al día y estábamos MALDECIENDO todos los índices para forzar a DB a reconstruir ambos índices y planes de ejecución de sproc después de cargar una nueva fecha y reconstruir todos los índices.

Por supuesto, teníamos un script separado para eso, ya que una vez que los sueltas, los índices ya no están en las tablas del sistema.

+0

La desactivación de un índice no agrupado mantiene la definición y permite recrear/reconstruir aproximadamente un 50% más rápido que la caída y la creación. – JNK

0

Usar un cursor para guiar las cosas es más idiomático que una tabla temporal (y un poco más breve). Para volver a habilitar los índices, reemplace DESACTIVAR con RECONSTRUIR.

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

Falta la palabra clave 'CURSOR' en la línea 1, creo. 'DECLARE cur_indexes CURSOR FOR' – Zack

+0

actualizado, gracias @Zack – kristianp

Cuestiones relacionadas