Evitar la comparacion por NULL ???

18/09/2006 - 01:34 por Marcelo Otero | Informe spam
Hola Gente: quisiera vuestra opinion acerca de un tema que no se como
remediarlo en algunas situaciones.
He visto, por ejemplo, que si en un JOIN entre 2 tablas en la clausula
WHERE se compara alguno de los campos por NULL o se usa la funcion ISNULL()
el mismo resulta mucho mas lento que si se evita la comparacion con NULL.

En un caso especifico el preguntar por si una fecha era NULL en el where ,
la consulta tardaba 16 segundos, cuando sacandola del where y armando la
consulta de tal manera de evitarla la misma tardo 5 seg.

Mi consulta es: es cierto que al usar NULL en el where los indices de las
tablas afectadas se desactivan y por eso es mas lenta la consulta? o es un
mito esto y solo la casualidad ha hecho que las consultas a las que he
eliminado la comprobacion por NULL o la funcion ISNULL() han sido mas
rapidas desde entonces?

Cordiales Saludos
Marcelo

Preguntas similare

Leer las respuestas

#6 BitOne®
19/09/2006 - 14:54 | Informe spam
Gracias alejandro :)
"Alejandro Mesa" wrote in message
news:
BitOne®,

Las expresiones que usastes en la clasula "where", evitan que SQL Server
haga un uso adecuado de los indices.

> Where IdEstado = case when @estado is not null then @estado else


idestado end


Ejemplo:

use northwind
go

create procedure dbo.p1
@orderid int = null
as
select *
from dbo.orders
where orderid = case when @orderid is null then orderid else @orderid end
go

set showplan_text on
go

exec dbo.p1
exec dbo.p1 '19980101'
go

set showplan_text off
go

drop procedure dbo.p1
go

Resultado:

exec dbo.p1

|--Clustered Index
Scan(OBJECT:([northwind].[dbo].[Orders].[PK_Orders]),
WHERE:([Orders].[OrderID]=If ([@orderid]=NULL) then [Orders].[OrderID]


else
[@orderid]))


exec dbo.p1 '19980101'

|--Clustered Index
Scan(OBJECT:([northwind].[dbo].[Orders].[PK_Orders]),
WHERE:([Orders].[OrderID]=If ([@orderid]=NULL) then [Orders].[OrderID]


else
[@orderid]))


Como podras notar, SQL Server hace un scan del indice clustered en ambos
casos. Cuando el valor de la variavble es NULL, SQL Server debe comparar


la
columna [orderid] consigo misma por cada fila para evaluar la expresion
logica.

Te recomiendo que si puedes leas estos dos magnificos articulos sobre el


tema.

Dynamic Search Conditions in T-SQL
http://www.sommarskog.se/dyn-search.html

Las virtudes y maldades del SQL dinámico
http://www.hayes.ch/sql/sql_dinamico.html


AMB

"BitOne®" wrote:

> como no tengo la data he armado una consulta para que pruebes con esta a


ver
> como te va, y me dices.
>
> if object_id('paObtenerMovimientosPendientes_prueba','P') is not null
> drop procedure paObtenerMovimientosPendientes_prueba
> go
> create procedure paObtenerMovimientosPendientes_prueba
> @FechaDesde varchar(10) = NULL
> ,@FechaHasta varchar(10) = NULL
> ,@FechaCarga varchar(10) = NULL
> ,@Estado int = NULL
> ,@Organizacion int = NULL
> ,@Movimiento int = NULL
> ,@Agente int = NULL
> ,@IdCola int = NULL
> AS
> begin
> select me.idcola,
> agente,
> couise,
> fechacarga,
> fechadesde,
> fechahasta,
> pm.rectificaa + movimiento as movimiento,
> me.estado,
> licencia,
> sitrev,
> pm.cupof
> From vwmoviemintosenviados me
> Inner join
> vwrObtenerPlazasDeMovimiento pm
> on pm.idcola = me.idcola
> Where IdEstado = case when @estado is not null then @estado
> else idestado end
> and idmovieminto = case when @movimiento is not null then


@movimiento
> else idmovimiento end
> and cuise = case when @organizacion is not null then
> @organizacion else cuise end
> and docuemnto = case when @agente is not null then @agente
> else docuemnto end
> and me.idcola = case when @idcola is not null then @idcola
> else me.idcola end
>
> end
>
>
> Saludos,
>
> > > BitOne®
> www.yocsql.com
>
> > >
> "Marcelo Otero" wrote in message
> news:%
> > Hola BITONE: envio el procedimiento en sus dos formatos, el primero es
> como
> > quedo actualmente donde tuve que crear una variable que vaya armando


la
> > consulta a medida que iba chequeando por NULLS mediante IF´s.Este
> > procedimiento ahora tarda menos de 5 segundos cuando antes tardaba mas


de
> > 17.(obs: un select de la consulta fue trasnformado en una vista pero


esto
> no
> > influyo en la performance, solo lo hizo el sacar la consulta por


nulls)
> >
> > Mas abajo (despues de ######) esta el procedimiento original el cual


hace
> lo
> > mismo pero los NULLS estan insertos en la clausula WHERE)
> >
> > CREATE PROCEDURE paObtenerMovimientosPendientes
> > @FechaDesde VARCHAR(10) = NULL,
> > @FechaHasta VARCHAR(10) = NULL,
> > @FechaCarga VARCHAR(10) = NULL,
> > @Estado INT = NULL,
> > @Organizacion INT = NULL,
> > @Movimiento INT = NULL,
> > @Agente INT = NULL,
> > @IdCola INT = NULL
> > AS
> >
> > DECLARE @Consulta varchar(5000)
> > SET @Consulta = 'SELECT ME.IdCola, Agente, CUISE, FechaCarga,


FechaDesde,
> > FechaHasta, PM.RectificaA + Movimiento AS Movimiento, ME.Estado,
> > Licencia, SitRev, PM.CUPOF
> > FROM vwMovimientosEnviados ME
> > INNER JOIN vwrObtenerPlazasDeMovimiento AS PM ON PM.IdCola = ME.IdCola
> WHERE
> > 1=1'
> >
> > IF @Estado IS NOT NULL
> > SET @Consulta = @Consulta + ' AND


IDEstado='+CONVERT(VARCHAR(2),@Estado)
> >
> > IF @Movimiento IS NOT NULL
> > SET @Consulta = @Consulta + ' AND
> > IDMovimiento='+CONVERT(VARCHAR(2),@Movimiento)
> >
> > IF @Organizacion IS NOT NULL
> > SET @Consulta = @Consulta + ' AND
> > CUISE='+CONVERT(VARCHAR(10),@Organizacion)
> >
> > IF @Agente IS NOT NULL
> > SET @Consulta = @Consulta + ' AND
> Documento='+CONVERT(VARCHAR(12),@Agente)
> >
> > IF @IdCola IS NOT NULL
> > SET @Consulta = @Consulta + ' AND
> Me.IdCola='+CONVERT(VARCHAR(12),@IdCola)
> >
> > SET @Consulta = @Consulta +' ORDER BY Fecha DESC'
> >
> > EXEC (@Consulta)
> >
> >
> > GO
> >
> > ##########################################################
> >
> > CREATE PROCEDURE paObtenerMovimientosPendientes
> > @FechaDesde VARCHAR(10) = NULL,
> > @FechaHasta VARCHAR(10) = NULL,
> > @FechaCarga VARCHAR(10) = NULL,
> > @Estado INT = NULL,
> > @Organizacion INT = NULL,
> > @Movimiento INT = NULL,
> > @Agente INT = NULL,
> > @IdCola INT = NULL
> > AS
> >
> > SELECT ME.IdCola, Agente, CUISE, FechaCarga, FechaDesde, FechaHasta,
> > PM.RectificaA + Movimiento AS Movimiento, ME.Estado,
> > Licencia, SitRev, PM.CUPOF
> > FROM vwMovimientosEnviados ME
> > INNER JOIN
> > (
> > SELECT IdCola, MIN(CUPOF) AS CUPOF, MIN(CASE WHEN RectificaA IS NULL
> THEN
> > '' ELSE 'R' END) AS RectificaA
> > FROM tb_PlazasDeMovimiento M
> > INNER JOIN tb_Plazas P ON P.IdPlaza = M.IdPlaza
> > GROUP BY IdCola
> > ) AS PM ON PM.IdCola = ME.IdCola
> > WHERE (IdEstado = isnull(@Estado,IdEstado)) AND
> > (IdMovimiento = isnull(@Movimiento,IdMovimiento)) AND
> > (CUISE = isnull(@Organizacion,CUISE))
> > AND (Documento = isnull(@Agente,Documento)) AND
> > (ME.IdCola = ISNULL(@IdCola, ME.IdCola))
> > ORDER BY Fecha DESC
> > GO
> >
> > > > >
> > "BitOne®" escribió en el mensaje
> > news:
> > > si nos dejaras ver esa consulta que dices pudieramo aclarar mejor tu
> duda
> > > eso por un lado,
> > > por el otro lado en la mayoria de los casas cuando utilizas


funciones en
> > > el
> > > predicado o Where
> > > estaras contribuyendo a que el motor de base de datos utilize un


table
> > > Scan
> > > en busca de
> > > recuperar las filas que complen con la condicion.
> > >
> > > saludos,
> > >
> > > ==> > > > BitoOne®
> > > www.yocsql.com
> > >
> > > ==> > > >
> > > "Marcelo Otero" wrote in message
> > > news:
> > >> Hola Gente: quisiera vuestra opinion acerca de un tema que no se


como
> > >> remediarlo en algunas situaciones.
> > >> He visto, por ejemplo, que si en un JOIN entre 2 tablas en la


clausula
> > >> WHERE se compara alguno de los campos por NULL o se usa la funcion
> > > ISNULL()
> > >> el mismo resulta mucho mas lento que si se evita la comparacion con
> NULL.
> > >>
> > >> En un caso especifico el preguntar por si una fecha era NULL en el
> where
> > >> ,
> > >> la consulta tardaba 16 segundos, cuando sacandola del where y


armando
> la
> > >> consulta de tal manera de evitarla la misma tardo 5 seg.
> > >>
> > >> Mi consulta es: es cierto que al usar NULL en el where los indices


de
> las
> > >> tablas afectadas se desactivan y por eso es mas lenta la consulta?


o es
> > >> un
> > >> mito esto y solo la casualidad ha hecho que las consultas a las que


he
> > >> eliminado la comprobacion por NULL o la funcion ISNULL() han sido


mas
> > >> rapidas desde entonces?
> > >>
> > >> Cordiales Saludos
> > >> Marcelo
> > >>
> > >>
> > >
> > >
> >
> >
>
>
>
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida