SQLServer 2000 me mantiene divertido...

Estaba analizando algunas sentencias que estaban lentas en un servidor de producción. Había una que era muy sencilla, pero que realizaba muchas lecturas, a pesar de tener la clave primaria instanciada, por lo que me puse a analizarla con un poco mas de detalle.

La tabla es bien sencilla y tiene

Tabla [TRVIAJE]
*TrVjId N(16) //Numero del viaje
TrVjSts C(3) //estado
TrVjFch Date //fecha del viaje.

En el Query Analyzer hago

DECLARE @TRVJID DECIMAL(16, 0)
SET @TRVJID=1000
SELECT TRVJID, TrVjSts FROM TRVIAJE (NOLOCK) WHERE TRVJID=@TRVJID ORDER BY TRVJID

El plan de ejecución es (que es el adecuado)
|--Clustered Index
Seek(OBJECT:([Base].[dbo].[TRVIAJE].[PK__TRVIAJE__4AD81681]),
SEEK:([TRVIAJE].[TRVJID]=[@TRVJID]) ORDERED FORWARD)

Pero si hago

DECLARE @TRVJID DECIMAL(18, 0) --Cambio de 16 a 18 el largo de la variable
SET @TRVJID=1000
SELECT TRVJID, TrVjSts FROM TRVIAJE (NOLOCK) WHERE TRVJID=@TRVJID ORDER BY TRVJID

el plan de ejecución elegido es:

|--Bookmark Lookup(BOOKMARK:([Bmk1000]), OBJECT:([Tica].[dbo].[TRVIAJE]))
|--Parallelism(Gather Streams)
|--Index Scan(OBJECT:([Base].[dbo].[TRVIAJE].[UTRVIFEC]), WHERE:([TRVIAJE].[TRVJID]=[@TRVJID]))


donde el indice UTRVIFEC, es por el campo TrVjFch, que ni siquiera está en la consulta!! y por supuesto hace más lecturas y demora bastante en devolver el resultado.

Pude encontrar algunas "explicaciones" a este comportamiento anormal en el blog del grupo de optimizacion de SQLServer (que recomiendan el uso de hints, que no se pueden aplicar en este caso) y en el sitio de soporte de Microsoft y en el WebSAC de Artech.

Sólo pudimos reproducir este problema en servidores de varios procesadores.

No podíamos achicar el atributo porque la reorganización hubiese demorado demasiado, pues estaba en varias tablas.

Los pasos que seguimos para lograr solucionar este problema fueron:
a) Poner la propiedad del modelo "Reorganize Server Tables" en *NO
b) Cambiar el atributo de N(18) a N(14). Se podia hacer porque en los próximos dos años no se iban a alcanzar los limites de guardar 14 digitos.
c) Regenerar todos los programas involucrados
d) Volver la propiedad del modelo a *YES

De esta forma, las sentencias generadas se realizaran con numeros mas chicos y SQLServer no tendra tantos problemas.

En resumen, una solución "mala pero nuestra".

Comentarios

Entradas más populares de este blog

Aplicación monolítica o distribuida?

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Funcionalidades de GeneXus que vale la pena conocer: DATE Constants.