Diario de SQL Server

Mover índices nonclustered a otro filegroup

Escrito por qwalgrande 23-01-2010 en General. Comentarios (0)

Una pregunta lanzada en el foro me recordó una cuenta pendiente que tenía con mi amigo Juan Carlos Sáez desde ¡casi tres años! Me pasó unas mejoras para un procedimiento que previamente había publicado en www.portalsql.com, cuya finalidad consistía en mover los índices nonclustered de un filegroup a otro.

 

La utilidad de ello está en la ganancia de rendmimiento que se consigue separando los índices no agrupados de los datos. No es una mejora muy sustancial, pero es una recomendación de rendimiento. Este procedimiento nos ayuda a preparar las sentencias necesarias para llevar a cabo tal acción.

 

Las notas que recibí en su momento de Juan Carlos fueron estas:

- Se centra sólo en hacer las cosas para las que ha sido escrito: mover los índices no cluster de un filegroup a otro.
- Permite mover los índices que soportan las PK de las tablas sin necesidad de bajar la PK antes (menudo follón que se monta si no puedes hacer esto con las FK's asociadas a la PK).
- Permite seleccionar el filegroup origen y destino, por si llegado el caso necesitas mover indices una segunda vez a otro filegroup de indices o devolverlos a su filegroup original
- Permite generar la sentencia SQL que mueve los índices o ejecutarla directamente. Muy útil si lo incluyes como una tarea más de mantenimiento para reubicar los índices que se han creado sin tener en cuenta el filegroup correcto.
- Para filtrar los índices que quiero mover, como por ejemplo excluir las estadísticas, me he basado en funciones documentadas evitando el uso de campos reservedos de las tablas.

 

Nada más, pego el código del procedimiento. Y por supuesto, gracias, Juan Carlos. Perdona el retraso.

 

 

 

 

IF EXISTS (SELECT *

FROM dbo.sysobjects

WHERE id = Object_id(N'[dbo].[sp_MoveNonClusterIndexes]')

AND Objectproperty(id,N'IsProcedure') = 1)

DROP PROCEDURE [dbo].[sp_movenonclusterindexes]

GO

CREATE PROCEDURE sp_MoveNonClusterIndexes(

@FromFilegroup VARCHAR(250)

,@ToFilegroup VARCHAR(250)

,@OnlyGenerateSentences int=1)

AS

/*

This procedure generates the DML sentences to move indexes currently in

in file group @FromFilegroup to file group @ToFilegroup.

Then, the sentences can be either run at your own convenience

or directly depending on the value of @OnlyGenerateSentences.

This script could be run periodically to locate indexes in the

wrong file group

*/

SET nocount ON

DECLARE @objname SYSNAME

,@indid INT

,@keys VARCHAR(2500)

,@objid INT

,@isunique INT

,@isuniqueclause VARCHAR(50)

,@Index_name VARCHAR(255)

,@Query NVARCHAR(4000)

,@res int

,@i INT

,@thiskey NVARCHAR(131) -- 128+3

IF object_id('tempdb..#indexes') > 0

DROP TABLE #indexes

SELECT user_name(uid) + '.' + o.name AS table_name

,o.id AS objid

,i.name AS index_name

,s.groupname AS filegroup

,i.indid

,Isnull(Indexproperty(o.id,i.name,'IsUnique'),0) IsUnique

,CAST(NULL AS VARCHAR(2500)) AS keys

,CAST(NULL AS VARCHAR(4000)) AS query

INTO #indexes

FROM sysindexes i

INNER JOIN sysobjects o

ON i.id = o.id

INNER JOIN sysfilegroups s

ON i.groupid = s.groupid

WHERE indid > 1 --Exclude clustered indexes

AND indid < 255 --Exlude indexes on text fields

AND Indexproperty(o.id,i.name,'IsStatistics') = 0 --Exclude statistics

AND Indexproperty(o.id,i.name,'IsHypothetical') = 0 --Exclude Hypothetical

AND o.TYPE = 'u' --Only user tables, exclude system tables

AND s.groupname = @FromFilegroup

DECLARE cur CURSOR FOR

SELECT table_name

,objid

,index_name

,indid

,isunique

FROM #indexes

ORDER BY table_name,isunique desc,index_name

OPEN cur

FETCH NEXT FROM cur

INTO @objName

,@objid

,@Index_name

,@indid

,@isunique

WHILE @@FETCH_STATUS = 0

BEGIN

SELECT @keys = Quotename(Index_col(@objname,@indid,1),'[')

,@i = 2

IF (indexkey_property(@objid,@indid,1,'isdescending') = 1)

SELECT @keys = @keys + ' DESC'

SELECT @thiskey = Quotename(Index_col(@objname,@indid,@i),'[')

IF ((@thiskey IS NOT NULL )AND

(indexkey_property(@objid,@indid,@i,'isdescending') = 1))

SELECT @thiskey = @thiskey + ' DESC'

WHILE (@thiskey IS NOT NULL )

BEGIN

SELECT @keys = @keys + ', ' + @thiskey

,@i = @i + 1

SELECT @thiskey = Index_col(@objname,@indid,@i)

IF ((@thiskey IS NOT NULL ) AND

(indexkey_property(@objid,@indid,@i,'isdescending') = 1))

SELECT @thiskey = @thiskey + ' DESC'

END

IF @isunique= 0

SET @isuniqueclause=''

else

SET @isuniqueclause=' unique '

SELECT @Query = 'Create ' + @isuniqueclause + ' nonclustered index ' +

@Index_name + ' on ' + @objName + ' (' + @keys + ') with (drop_existing=on)

on [' + @ToFilegroup + '] '

IF @OnlyGenerateSentences =1

PRINT @Query + CHAR(13) + CHAR(10) + 'GO' + CHAR(13) + CHAR(10)

ELSE

BEGIN

RAISERROR ('Moving index %s.%s from %s to %s...

',0,1,@objName,@Index_name,@FromFilegroup,@ToFilegroup)with nowait

exec @res=sp_executesql @query

IF @res=0

RAISERROR (' Successfully moved index

%s.%s',0,1,@objName,@Index_name)with nowait

ELSE

RAISERROR (' ERROR moving index %s.%s ',0,1,@objName,@Index_name)with

nowait

END

FETCH NEXT FROM cur

INTO @objName

,@objid

,@Index_name

,@indid

,@isunique

END

DEALLOCATE cur

Go

print 'Now, you can execute :'

print ' exec sp_MoveNonClusterIndexes @FromFilegroup=''FromFileGroup'',

@ToFilegroup=''ToFilegroup'' , @OnlyGenerateSentences = 1 '

print 'For example: '

print ' exec sp_MoveNonClusterIndexes @FromFilegroup=''PRIMARY'',

@ToFilegroup=''INDEXES'' , @OnlyGenerateSentences = 1'

Error 1635: Unable to install Windows Installer MSP file

Escrito por qwalgrande 22-01-2010 en General. Comentarios (0)

Este procedimiento lo he tenido que poner en práctica hace poco y, la verdad, es bastante rebuscado. Espero que Microsoft implemente una solución más "suave" para la resolución de este problema. El origen se encuentra en que el parche a instalar requiere de algún otro parche aplicado con anterioridad, pero por el motivo que sea, dicho parche ya no se encuentra en la máquina.

 

En el caso concreto que he padecido, se trataba de instalar el parche acumulativo 7 del service pack 3 de SQL Server 2005. En otras circunstancias, recurres a desinstalar el service pack, instalarlo de nuevo y a partir de ahí, lo normal es que ya no se presente el problema, pero claro, la peguita está en que el Service Pack 3 de SQL Server 2005 no puede desinstalarse. Y ya reinstalar SQL Server 2005 de nuevo es demasiado, cualquier workaround, por grande que sea el rodeo, es preferible a esa alternativa.

 

El proceso detallado se encuentra en:

 

http://blogs.msdn.com/esecuelesinfronteras/archive/2008/11/21/error-number-1635-unable-to-install-windows-installer-msp-file.aspx

 

Pero lo resumo a modo de guía, ya que suele ser preciso repetirlo para muchos parches:

    1. Localizar nombre del .msp en el log de instalación.
    2. Buscar ese nombre en HKLM \SOFTWARE \Microsoft \Windows \CurrentVersion \Installer \UserData \S-1-5-18 \Patches para obtener una clave alfanumérica.
    3. Buscar la clave alfanumérica del paso 2 en HKLM \SOFTWARE \Microsoft \Windows \CurrentVersion \Installer \UserData \S-1-5-18 \Products para obtener el nombre del parche o service pack en el que se encontraba el .msp originariamente.
    4. Obtener ese parche de nuevo y descomprimirlo. Localizar el .msp concreto.
    5. Copiar en C:\Windows\Installer el .msp, dándole el nombre que figuraba en el log de instalación.
    6. Lanzar la instalación otra vez. Si vuelve a fallar, repetir los pasos.

 

Que no tengan que recurrir nunca a él.

Vendrán días

Escrito por qwalgrande 16-01-2010 en General. Comentarios (0)

Se podrían definir varios roles dentro de un DBA. La forma más simple ya la hacen desde Microsoft con las certificaciones: la administración, configuración, instalación y en general la parte física por un lado; y por otro, el diseño, modelado, programación y en general la parte desarrollo de aplicaciones (o para aplicaciones más bien). Según mi criterio, si bien la especialización puede ser una opción perfectamente válida, hay que saber un mínimo de ambos mundos para poder integrarlos adecuadamente y sacarles partido.

 

En mi caso, toco ambos palos. Tengo responsabilidades en el desarrollo y en los sistemas. Y la verdad, no es fácil. Por un lado tengo las constancias y premuras, las prisas de última hora en los días de entrega del proyecto que tan habituales son en el desarrollo de software. Por otro lado, tengo la tranquila supervisión, las intervenciones fuera de horario y, para mí lo peor de todo, las urgencias que provocan las caídas en el servicio, los gajes del oficio de los administradores de sistemas.

 

Es lo que peor llevo porque cualquier agenda, cualquier plan que uno tuviera se va al traste si se cae una máquina, porque lo primero, sin duda, es la disponibilidad, y todo lo demás ha de esperar. Es estresante y poco o nada agradecido (nadie llama nunca para comentarte lo bien que va todo y la de días o meses que hace que no hay un corte del servicio), pero si encima te trastoca los planes, que bien pudiera ser la finalización de un desarrollo que hay que terminar...

 

Una de esas me ha tocado a mí hoy. Un servicio de Integration Services, que no se dejaba arrancar, que me ha tenido más de tres horas desaparecido de la faz de la tierra. En fin...

 

Si estás pensando en especializarte por una de las dos ramas, ambas tienen sus ventajas y sus inconvenientes. Si tu objetivo es ser más completo y abarcar las dos partes, cuenta con días como el que yo he tenido hoy, porque vendrán. Otro día hablaré de las situaciones en las que no hay nada que puedas elegir, si no que se han de afrontar la globalidad de las áreas al no existir especialización, ni recursos, los brazos son los que son y cada cual trata de sumar aquello que puede.

 

Si era lo que buscabas, márcala como respuesta

Escrito por qwalgrande 03-01-2010 en General. Comentarios (0)

Son muchos los que pasan por el foro, pero no somos tantos los que estamos habitualmente en él. Es por ello que nos gusta que las cosas se hagan a la manera de los que participamos más activamente. No tiene por qué ser así, cada uno es libre de hacer aquello que le venga en gana, que para eso es un foro abierto a cualquiera que tenga a bien pasarse por él. Agradecemos que los post que procedan se marquen como respuestas, sobre todo si el que lo marca es el que realizó la pregunta. Sin embargo, es frecuente que se habra un hilo y nunca más se mire. Con muy buen criterio, los moderadores se encargan de hacer esa parte del trabajo, que consiste en marcar respuestas y cerrar hilos.

 

¿Cuál es la utilidad de marcar los hilos como respondidos (si procede)? Muy fácil. Alguien se tropieza con un error, lo pone en google y obtiene la hueva de links o ninguno. En el primer caso, Si uno ve que alguien ya pasó por aquello y obtuvo una respuesta que pudiera ayudarle, aunque fuera en parte, a salir del paso, irá directamente a por ella. Lo mismo, hasta le resuelve el problema que le ocupa en ese momento. Es muy posible que ese alguien obtenga una buena opinión del foro y que la próxima vez que tenga que solventar una papeleta recurra al foro, se sume a él como participante y aporte su experiencia, con lo que todos ganamos.

 

Si por el contrario, ese hilo en el que se encuentra la respuesta a su inconveniente no está marcado como tal, seguramente que ignore el contenido y prosiga su búsqueda por otros lares. Él no encuentra solución ni ayuda y los demás nos quedamos sin lo que ese alguien pudiera aportarnos a todos en el futuro.

 

Y se podrá pensar que se busca también que se marquen las respuestas de uno como las correctas. Pues bien, de serlo, sí. Lo único que obtenemos con ello, y no creo que sea poco, es reconocimiento, ya que difícilmente se puede pensar en obtener alguna otra cosa. Y por cursi que pueda parecer, saber que le has echado un cable a un compañero en un momento de dificultad.