Problema lentitud en consulta

25/11/2008 - 16:00 por Danilo Reinoso | Informe spam
Saludos

Utilizo SQL-Server 2000

tengo el siguiente query el cual cuando le pongo los parametros declarado
tarda mas de lo normal unos 25 seg,
y cuando le pongo los parametros directo tarda menos 0.02 seg.
Lo que puedo observar es que cuando utilizo los parametros declarado la
consulta hace un index scan, y cuando lo pongo
directo hace un seek sobre el campo [Fecha Movimiento].
Como podria corregir el query para que cuando use los parametros me pueda
usar el index del campo [Fecha Movimiento].

Este es el query:

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN) --
'20081124' AND '20081124')
AND (dbo.Historial.[Movido Hasta] = 'Scrap')
GROUP BY dbo.Historial.[Movido Desde], dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No]


********************
scripts de la tabla historial
********************

if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[Historial]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Historial]
GO

CREATE TABLE [dbo].[Historial] (
[Transaccion] [int] NOT NULL ,
[Numero Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Movido Desde] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Movido Hasta] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Fecha Movimiento] [datetime] NULL ,
[Hora Movimiento] [datetime] COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Item No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Item Descripcion] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Cantidad Aceptada] [float] NULL ,
[Peso Aceptada] [float] NULL ,
[Cantidad Rechazada] [float] NULL ,
[Peso Rechazada] [float] NULL ,
[Cantidad Dañada] [float] NULL ,
[Peso Dañada] [float] NULL ,
[Peso Piedras] [float] NULL ,
[Peso Extra] [float] NULL ,
[Descripcion Extra] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Peso Salida] [float] NULL ,
[Total Orden] [float] NULL ,
[Total Peso] [float] NULL ,
[Direccion Foto] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Ultimo_Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Empleado No] [int] NULL ,
[Empleado Nombre] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Operacion No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas_Mov] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Declarado] [bit] NULL ,
[Duracion] [float] NULL ,
[Usuario Sistema] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Status] [int] NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Historial] WITH NOCHECK ADD
CONSTRAINT [PK__Historial__2B3F6F97] PRIMARY KEY CLUSTERED
(
[Transaccion]
) ON [PRIMARY]
GO

CREATE INDEX [IndicePorItemNo] ON [dbo].[Historial]([Item No]) ON
[PRIMARY]
GO

CREATE INDEX [IndicePorNumeroTrabajo] ON [dbo].[Historial]([Numero
Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoDesde] ON [dbo].[Historial]([Movido Desde])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoHasta] ON [dbo].[Historial]([Movido Hasta])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorFechaMovimiento] ON [dbo].[Historial]([Fecha
Movimiento]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorEmpleadoNo] ON [dbo].[Historial]([Empleado No]) ON
[PRIMARY]
GO

CREATE INDEX [IndicePorOperacionNo] ON [dbo].[Historial]([Operacion No])
ON [PRIMARY]
GO

CREATE INDEX [Indice_Ultimo_Trabajo] ON
[dbo].[Historial]([Ultimo_Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IX_Descripcion_Extra] ON [dbo].[Historial]([Descripcion
Extra]) ON [PRIMARY]
GO


************************
Estos son los planes del query
************************

StmtText

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Inicial])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Final])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
-
SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN

(1 row(s) affected)

StmtText
-
|--Parallelism(Gather Streams)
|--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL else
[Expr1008]))
|--Stream Aggregate(GROUP BY:([Historial].[Item No],
[Historial].[Movido Desde])
DEFINE:([Expr1007]=COUNT_BIG([Historial].[Cantidad Aceptada]),
[Expr1008]=SUM([Historial].[Cantidad Aceptada]), [Historial].[Movido
Hasta]=ANY([Historial].[Movido
|--Sort(ORDER BY:([Historial].[Item No] ASC,
[Historial].[Movido Desde] ASC))
|--Parallelism(Repartition Streams, PARTITION
COLUMNS:([Historial].[Item No], [Historial].[Movido Desde]))
|--Clustered Index
Scan(OBJECT:([GCSERVIDOR].[dbo].[Historial].[PK__Historial__2B3F6F97]),
WHERE:(([Historial].[Fecha Movimiento]>=[@DT_INI] AND [Historial].[Fecha
Movimiento]<=[@DT_FIN]) AND [Historial].[Movido Hasta]='Scrap'))

(6 row(s) affected)

Gracias por su ayuda.

Preguntas similare

Leer las respuestas

#1 Alejandro Mesa
25/11/2008 - 16:47 | Informe spam
Danilo Reinoso,

Estas haciendo la prueba desde QA o SSMS directamente?

Si es asi, te aconsejo que hagas la prueba creando un procedimiento
almacenado, o que si insistes en hacerlo desde QA, que uses sp_executesql. Lo
que pasa es que no usas parametros sino variables, que es diferente o que SQL
Server emplea de forma diferente cuando estima la cardinalidad basada en el
join y los filtros en la clausula where.

Que pasa si haces:

declare @sql nvarchar(4000)
DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

set @sql = N'
SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
'

exec sp_executesql @sql, N'@DT_INI datetime, @DT_FIN datetime', @DT_INI,
@DT_FIN
GO

Si lo vas a hacer con us sp, tendras que usar la opcion "OPTION (RECOMPILE)"
en la sentencia select para que recompile la sentencia durante la ejecucion
y pueda usar los valores de las variables para estimar cardinalidad, lo malo
es que el plan de ejecucion de esta sentencia no se reusara. Tambien
puedespartir el sp en dos, poniendo la ultima sentencia select en un sp por
separado para que este sea llamado por un sp que assigna primero los valores
a las variables @DT_INI y @DT_FIN y luego usa estas variables para pasar
valores a los parametros de entrada de el segundo sp. Esto se debe a que
durante la compilacion, SQL Server no sabe los valores de las variables, por
lo que no puede hacer un estimado correecto de la cardinalidad y uso otro
mecanismo para ello.

create dbo.usp_p1
@DT_INI datetime,
@DT_FIN datetime
as
set nocount on

SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
GO

create dbo.usp_p2
as
set nocount on

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

exec dbo.usp_p1 @DT_INI, @DT_FIN
GO

EXEC dbo.usp_p2
GO

o puedes hacer lo sgte, si usas SS 2005 / 2008.

create dbo.usp_p1
as
set nocount on

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
OPTION (RECOMPILE)
GO


AMB

"Danilo Reinoso" wrote:

Saludos

Utilizo SQL-Server 2000

tengo el siguiente query el cual cuando le pongo los parametros declarado
tarda mas de lo normal unos 25 seg,
y cuando le pongo los parametros directo tarda menos 0.02 seg.
Lo que puedo observar es que cuando utilizo los parametros declarado la
consulta hace un index scan, y cuando lo pongo
directo hace un seek sobre el campo [Fecha Movimiento].
Como podria corregir el query para que cuando use los parametros me pueda
usar el index del campo [Fecha Movimiento].

Este es el query:

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN) --
'20081124' AND '20081124')
AND (dbo.Historial.[Movido Hasta] = 'Scrap')
GROUP BY dbo.Historial.[Movido Desde], dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No]


********************
scripts de la tabla historial
********************

if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[Historial]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[Historial]
GO

CREATE TABLE [dbo].[Historial] (
[Transaccion] [int] NOT NULL ,
[Numero Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Movido Desde] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Movido Hasta] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Fecha Movimiento] [datetime] NULL ,
[Hora Movimiento] [datetime] COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Item No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Item Descripcion] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Cantidad Aceptada] [float] NULL ,
[Peso Aceptada] [float] NULL ,
[Cantidad Rechazada] [float] NULL ,
[Peso Rechazada] [float] NULL ,
[Cantidad Dañada] [float] NULL ,
[Peso Dañada] [float] NULL ,
[Peso Piedras] [float] NULL ,
[Peso Extra] [float] NULL ,
[Descripcion Extra] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Peso Salida] [float] NULL ,
[Total Orden] [float] NULL ,
[Total Peso] [float] NULL ,
[Direccion Foto] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Ultimo_Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Empleado No] [int] NULL ,
[Empleado Nombre] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Operacion No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas_Mov] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Declarado] [bit] NULL ,
[Duracion] [float] NULL ,
[Usuario Sistema] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Status] [int] NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Historial] WITH NOCHECK ADD
CONSTRAINT [PK__Historial__2B3F6F97] PRIMARY KEY CLUSTERED
(
[Transaccion]
) ON [PRIMARY]
GO

CREATE INDEX [IndicePorItemNo] ON [dbo].[Historial]([Item No]) ON
[PRIMARY]
GO

CREATE INDEX [IndicePorNumeroTrabajo] ON [dbo].[Historial]([Numero
Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoDesde] ON [dbo].[Historial]([Movido Desde])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoHasta] ON [dbo].[Historial]([Movido Hasta])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorFechaMovimiento] ON [dbo].[Historial]([Fecha
Movimiento]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorEmpleadoNo] ON [dbo].[Historial]([Empleado No]) ON
[PRIMARY]
GO

CREATE INDEX [IndicePorOperacionNo] ON [dbo].[Historial]([Operacion No])
ON [PRIMARY]
GO

CREATE INDEX [Indice_Ultimo_Trabajo] ON
[dbo].[Historial]([Ultimo_Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IX_Descripcion_Extra] ON [dbo].[Historial]([Descripcion
Extra]) ON [PRIMARY]
GO


************************
Estos son los planes del query
************************

StmtText

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Inicial])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Final])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
-
SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN

(1 row(s) affected)

StmtText
-
|--Parallelism(Gather Streams)
|--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL else
[Expr1008]))
|--Stream Aggregate(GROUP BY:([Historial].[Item No],
[Historial].[Movido Desde])
DEFINE:([Expr1007]=COUNT_BIG([Historial].[Cantidad Aceptada]),
[Expr1008]=SUM([Historial].[Cantidad Aceptada]), [Historial].[Movido
Hasta]=ANY([Historial].[Movido
|--Sort(ORDER BY:([Historial].[Item No] ASC,
[Historial].[Movido Desde] ASC))
|--Parallelism(Repartition Streams, PARTITION
COLUMNS:([Historial].[Item No], [Historial].[Movido Desde]))
|--Clustered Index
Scan(OBJECT:([GCSERVIDOR].[dbo].[Historial].[PK__Historial__2B3F6F97]),
WHERE:(([Historial].[Fecha Movimiento]>=[@DT_INI] AND [Historial].[Fecha
Movimiento]<=[@DT_FIN]) AND [Historial].[Movido Hasta]='Scrap'))

(6 row(s) affected)

Gracias por su ayuda.



Respuesta Responder a este mensaje
#2 Danilo Reinoso
25/11/2008 - 17:26 | Informe spam
Gracias Alejandro por responder

Te comento que la prueba la estoy realizando desde el query analizer, y la
consulta tambien pertenece a un procedimiento almacenado, lo que pasa es que
estoy
depurando porque el store procedure tarda tanto y esta es la query que esta
dando el problema.



"Alejandro Mesa" wrote in message
news:
Danilo Reinoso,

Estas haciendo la prueba desde QA o SSMS directamente?

Si es asi, te aconsejo que hagas la prueba creando un procedimiento
almacenado, o que si insistes en hacerlo desde QA, que uses sp_executesql.
Lo
que pasa es que no usas parametros sino variables, que es diferente o que
SQL
Server emplea de forma diferente cuando estima la cardinalidad basada en
el
join y los filtros en la clausula where.

Que pasa si haces:

declare @sql nvarchar(4000)
DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

set @sql = N'
SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
'

exec sp_executesql @sql, N'@DT_INI datetime, @DT_FIN datetime', @DT_INI,
@DT_FIN
GO

Si lo vas a hacer con us sp, tendras que usar la opcion "OPTION
(RECOMPILE)"
en la sentencia select para que recompile la sentencia durante la
ejecucion
y pueda usar los valores de las variables para estimar cardinalidad, lo
malo
es que el plan de ejecucion de esta sentencia no se reusara. Tambien
puedespartir el sp en dos, poniendo la ultima sentencia select en un sp
por
separado para que este sea llamado por un sp que assigna primero los
valores
a las variables @DT_INI y @DT_FIN y luego usa estas variables para pasar
valores a los parametros de entrada de el segundo sp. Esto se debe a que
durante la compilacion, SQL Server no sabe los valores de las variables,
por
lo que no puede hacer un estimado correecto de la cardinalidad y uso otro
mecanismo para ello.

create dbo.usp_p1
@DT_INI datetime,
@DT_FIN datetime
as
set nocount on

SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
GO

create dbo.usp_p2
as
set nocount on

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

exec dbo.usp_p1 @DT_INI, @DT_FIN
GO

EXEC dbo.usp_p2
GO

o puedes hacer lo sgte, si usas SS 2005 / 2008.

create dbo.usp_p1
as
set nocount on

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
OPTION (RECOMPILE)
GO


AMB

"Danilo Reinoso" wrote:

Saludos

Utilizo SQL-Server 2000

tengo el siguiente query el cual cuando le pongo los parametros declarado
tarda mas de lo normal unos 25 seg,
y cuando le pongo los parametros directo tarda menos 0.02 seg.
Lo que puedo observar es que cuando utilizo los parametros declarado la
consulta hace un index scan, y cuando lo pongo
directo hace un seek sobre el campo [Fecha Movimiento].
Como podria corregir el query para que cuando use los parametros me pueda
usar el index del campo [Fecha Movimiento].

Este es el query:

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN) --
'20081124' AND '20081124')
AND (dbo.Historial.[Movido Hasta] = 'Scrap')
GROUP BY dbo.Historial.[Movido Desde], dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No]


********************
scripts de la tabla historial
********************

if exists (select * from dbo.sysobjects where id >> object_id(N'[dbo].[Historial]') and OBJECTPROPERTY(id, N'IsUserTable') =
1)
drop table [dbo].[Historial]
GO

CREATE TABLE [dbo].[Historial] (
[Transaccion] [int] NOT NULL ,
[Numero Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Movido Desde] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Movido Hasta] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Fecha Movimiento] [datetime] NULL ,
[Hora Movimiento] [datetime] COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Item No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Item Descripcion] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL
,
[Cantidad Aceptada] [float] NULL ,
[Peso Aceptada] [float] NULL ,
[Cantidad Rechazada] [float] NULL ,
[Peso Rechazada] [float] NULL ,
[Cantidad Dañada] [float] NULL ,
[Peso Dañada] [float] NULL ,
[Peso Piedras] [float] NULL ,
[Peso Extra] [float] NULL ,
[Descripcion Extra] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Peso Salida] [float] NULL ,
[Total Orden] [float] NULL ,
[Total Peso] [float] NULL ,
[Direccion Foto] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Ultimo_Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Empleado No] [int] NULL ,
[Empleado Nombre] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL
,
[Operacion No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Notas] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas_Mov] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Declarado] [bit] NULL ,
[Duracion] [float] NULL ,
[Usuario Sistema] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL
,
[Status] [int] NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Historial] WITH NOCHECK ADD
CONSTRAINT [PK__Historial__2B3F6F97] PRIMARY KEY CLUSTERED
(
[Transaccion]
) ON [PRIMARY]
GO

CREATE INDEX [IndicePorItemNo] ON [dbo].[Historial]([Item No]) ON
[PRIMARY]
GO

CREATE INDEX [IndicePorNumeroTrabajo] ON [dbo].[Historial]([Numero
Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoDesde] ON [dbo].[Historial]([Movido
Desde])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoHasta] ON [dbo].[Historial]([Movido
Hasta])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorFechaMovimiento] ON [dbo].[Historial]([Fecha
Movimiento]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorEmpleadoNo] ON [dbo].[Historial]([Empleado No])
ON
[PRIMARY]
GO

CREATE INDEX [IndicePorOperacionNo] ON [dbo].[Historial]([Operacion
No])
ON [PRIMARY]
GO

CREATE INDEX [Indice_Ultimo_Trabajo] ON
[dbo].[Historial]([Ultimo_Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IX_Descripcion_Extra] ON [dbo].[Historial]([Descripcion
Extra]) ON [PRIMARY]
GO


************************
Estos son los planes del query
************************

StmtText

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)

(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Inicial])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos
Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Final])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos
Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
-
SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN

(1 row(s) affected)

StmtText
-
|--Parallelism(Gather Streams)
|--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL
else
[Expr1008]))
|--Stream Aggregate(GROUP BY:([Historial].[Item No],
[Historial].[Movido Desde])
DEFINE:([Expr1007]=COUNT_BIG([Historial].[Cantidad Aceptada]),
[Expr1008]=SUM([Historial].[Cantidad Aceptada]), [Historial].[Movido
Hasta]=ANY([Historial].[Movido
|--Sort(ORDER BY:([Historial].[Item No] ASC,
[Historial].[Movido Desde] ASC))
|--Parallelism(Repartition Streams, PARTITION
COLUMNS:([Historial].[Item No], [Historial].[Movido Desde]))
|--Clustered Index
Scan(OBJECT:([GCSERVIDOR].[dbo].[Historial].[PK__Historial__2B3F6F97]),
WHERE:(([Historial].[Fecha Movimiento]>=[@DT_INI] AND [Historial].[Fecha
Movimiento]<=[@DT_FIN]) AND [Historial].[Movido Hasta]='Scrap'))

(6 row(s) affected)

Gracias por su ayuda.



Respuesta Responder a este mensaje
#3 Danilo Reinoso
25/11/2008 - 17:47 | Informe spam
Gracias Alejandro por tus sugerencias

Utilice la opcion de crear dos store procedure y de esta forma ya se ejecuta
mucho mas rapido.

Este es el store procedure que llama el anterior pasandole los dos
parametros.

CREATE PROCEDURE USP_Sum_FinScrap_By_Depto1 AS

SET NOCOUNT ON

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

EXEC dbo.USP_Sum_FinScrap_By_Depto @DT_INI, @DT_Fin
GO

una vez mas gracias por tu ayuda..


"Alejandro Mesa" wrote in message
news:
Danilo Reinoso,

Estas haciendo la prueba desde QA o SSMS directamente?

Si es asi, te aconsejo que hagas la prueba creando un procedimiento
almacenado, o que si insistes en hacerlo desde QA, que uses sp_executesql.
Lo
que pasa es que no usas parametros sino variables, que es diferente o que
SQL
Server emplea de forma diferente cuando estima la cardinalidad basada en
el
join y los filtros en la clausula where.

Que pasa si haces:

declare @sql nvarchar(4000)
DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

set @sql = N'
SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
'

exec sp_executesql @sql, N'@DT_INI datetime, @DT_FIN datetime', @DT_INI,
@DT_FIN
GO

Si lo vas a hacer con us sp, tendras que usar la opcion "OPTION
(RECOMPILE)"
en la sentencia select para que recompile la sentencia durante la
ejecucion
y pueda usar los valores de las variables para estimar cardinalidad, lo
malo
es que el plan de ejecucion de esta sentencia no se reusara. Tambien
puedespartir el sp en dos, poniendo la ultima sentencia select en un sp
por
separado para que este sea llamado por un sp que assigna primero los
valores
a las variables @DT_INI y @DT_FIN y luego usa estas variables para pasar
valores a los parametros de entrada de el segundo sp. Esto se debe a que
durante la compilacion, SQL Server no sabe los valores de las variables,
por
lo que no puede hacer un estimado correecto de la cardinalidad y uso otro
mecanismo para ello.

create dbo.usp_p1
@DT_INI datetime,
@DT_FIN datetime
as
set nocount on

SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
GO

create dbo.usp_p2
as
set nocount on

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

exec dbo.usp_p1 @DT_INI, @DT_FIN
GO

EXEC dbo.usp_p2
GO

o puedes hacer lo sgte, si usas SS 2005 / 2008.

create dbo.usp_p1
as
set nocount on

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME

SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

SELECT
[Movido Desde],
[Movido Hasta],
[Item No],
SUM([Cantidad Aceptada]) AS Total_Qty
FROM
dbo.Historial
WHERE
([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
AND ([Movido Hasta] = 'Scrap')
GROUP BY
[Movido Desde],
[Movido Hasta],
[Item No]
OPTION (RECOMPILE)
GO


AMB

"Danilo Reinoso" wrote:

Saludos

Utilizo SQL-Server 2000

tengo el siguiente query el cual cuando le pongo los parametros declarado
tarda mas de lo normal unos 25 seg,
y cuando le pongo los parametros directo tarda menos 0.02 seg.
Lo que puedo observar es que cuando utilizo los parametros declarado la
consulta hace un index scan, y cuando lo pongo
directo hace un seek sobre el campo [Fecha Movimiento].
Como podria corregir el query para que cuando use los parametros me pueda
usar el index del campo [Fecha Movimiento].

Este es el query:

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN) --
'20081124' AND '20081124')
AND (dbo.Historial.[Movido Hasta] = 'Scrap')
GROUP BY dbo.Historial.[Movido Desde], dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No]


********************
scripts de la tabla historial
********************

if exists (select * from dbo.sysobjects where id >> object_id(N'[dbo].[Historial]') and OBJECTPROPERTY(id, N'IsUserTable') =
1)
drop table [dbo].[Historial]
GO

CREATE TABLE [dbo].[Historial] (
[Transaccion] [int] NOT NULL ,
[Numero Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Movido Desde] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Movido Hasta] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Fecha Movimiento] [datetime] NULL ,
[Hora Movimiento] [datetime] COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Item No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Item Descripcion] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL
,
[Cantidad Aceptada] [float] NULL ,
[Peso Aceptada] [float] NULL ,
[Cantidad Rechazada] [float] NULL ,
[Peso Rechazada] [float] NULL ,
[Cantidad Dañada] [float] NULL ,
[Peso Dañada] [float] NULL ,
[Peso Piedras] [float] NULL ,
[Peso Extra] [float] NULL ,
[Descripcion Extra] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Peso Salida] [float] NULL ,
[Total Orden] [float] NULL ,
[Total Peso] [float] NULL ,
[Direccion Foto] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Ultimo_Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL ,
[Empleado No] [int] NULL ,
[Empleado Nombre] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL
,
[Operacion No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
,
[Notas] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Notas_Mov] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Declarado] [bit] NULL ,
[Duracion] [float] NULL ,
[Usuario Sistema] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
NULL
,
[Status] [int] NULL
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[Historial] WITH NOCHECK ADD
CONSTRAINT [PK__Historial__2B3F6F97] PRIMARY KEY CLUSTERED
(
[Transaccion]
) ON [PRIMARY]
GO

CREATE INDEX [IndicePorItemNo] ON [dbo].[Historial]([Item No]) ON
[PRIMARY]
GO

CREATE INDEX [IndicePorNumeroTrabajo] ON [dbo].[Historial]([Numero
Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoDesde] ON [dbo].[Historial]([Movido
Desde])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorMovidoHasta] ON [dbo].[Historial]([Movido
Hasta])
ON [PRIMARY]
GO

CREATE INDEX [IndicePorFechaMovimiento] ON [dbo].[Historial]([Fecha
Movimiento]) ON [PRIMARY]
GO

CREATE INDEX [IndicePorEmpleadoNo] ON [dbo].[Historial]([Empleado No])
ON
[PRIMARY]
GO

CREATE INDEX [IndicePorOperacionNo] ON [dbo].[Historial]([Operacion
No])
ON [PRIMARY]
GO

CREATE INDEX [Indice_Ultimo_Trabajo] ON
[dbo].[Historial]([Ultimo_Trabajo]) ON [PRIMARY]
GO

CREATE INDEX [IX_Descripcion_Extra] ON [dbo].[Historial]([Descripcion
Extra]) ON [PRIMARY]
GO


************************
Estos son los planes del query
************************

StmtText

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM
SVRSOLDATA.DBO.v_Datos_Reportes)

(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Inicial])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos
Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)




(1 row(s) affected)

StmtText

|--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
|--Nested Loops(Left Outer Join)
|--Constant Scan
|--Assert(WHERE:(If ([Expr1008]>1) then 0 else NULL))
|--Stream Aggregate(DEFINE:([Expr1008]=Count(*),
[Expr1009]=ANY([Datos Reportes].[Fecha Final])))
|--Bookmark Lookup(BOOKMARK:([Bmk1003]),
OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes]))
|--Nested Loops(Inner Join, OUTER
REFERENCES:([Expr1002]))
|--Stream
Aggregate(DEFINE:([Expr1002]=MAX([Datos Reportes].[Fecha Creacion])))
| |--Top(1)
| |--Filter(WHERE:(([Datos
Reportes].[Fecha Creacion] IS NOT NULL) AND [Datos
Reportes].[Net_Address]=[dbo].[fn_SPIDTONETADDR]()))
| |--Bookmark
Lookup(BOOKMARK:([Bmk1000]), OBJECT:([SVRSOLDATA].[dbo].[Datos
Reportes]))
| |--Index
Scan(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
ORDERED BACKWARD)
|--Index
Seek(OBJECT:([SVRSOLDATA].[dbo].[Datos Reportes].[IX_FechaCreacion]),
SEEK:([Datos Reportes].[Fecha Creacion]=[Expr1002]) ORDERED FORWARD)

(13 row(s) affected)

StmtText
-
SELECT dbo.Historial.[Movido Desde],
dbo.Historial.[Movido Hasta],
dbo.Historial.[Item No],
SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
FROM dbo.Historial
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN

(1 row(s) affected)

StmtText
-
|--Parallelism(Gather Streams)
|--Compute Scalar(DEFINE:([Expr1002]=If ([Expr1007]=0) then NULL
else
[Expr1008]))
|--Stream Aggregate(GROUP BY:([Historial].[Item No],
[Historial].[Movido Desde])
DEFINE:([Expr1007]=COUNT_BIG([Historial].[Cantidad Aceptada]),
[Expr1008]=SUM([Historial].[Cantidad Aceptada]), [Historial].[Movido
Hasta]=ANY([Historial].[Movido
|--Sort(ORDER BY:([Historial].[Item No] ASC,
[Historial].[Movido Desde] ASC))
|--Parallelism(Repartition Streams, PARTITION
COLUMNS:([Historial].[Item No], [Historial].[Movido Desde]))
|--Clustered Index
Scan(OBJECT:([GCSERVIDOR].[dbo].[Historial].[PK__Historial__2B3F6F97]),
WHERE:(([Historial].[Fecha Movimiento]>=[@DT_INI] AND [Historial].[Fecha
Movimiento]<=[@DT_FIN]) AND [Historial].[Movido Hasta]='Scrap'))

(6 row(s) affected)

Gracias por su ayuda.



Respuesta Responder a este mensaje
#4 Alejandro Mesa
25/11/2008 - 18:27 | Informe spam
Danilo Reinoso,

Chequea el nuevo plan. Algo se me paso mencionar, y es que si vas a usar
esta query constantemente, quizas debas analizar cambiar el indice clustered
en la tabla [Historial] puesto que actualmente lo tienes por la columna
[Transaccion], y esto hace que la expresion de rango forze a SQL Server a
hacer un scan de el indice clustered.

...
WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN

|--Clustered Index
Scan(OBJECT:([GCSERVIDOR].[dbo].[Historial].[PK__Historial__2B3F6F97]),
WHERE:(([Historial].[Fecha Movimiento]>=[@DT_INI] AND [Historial].[Fecha
Movimiento]<=[@DT_FIN]) AND [Historial].[Movido Hasta]='Scrap'))

Pudieras cambiar la clave primaria para que use un indice nonclustered y
crear el clustered por la columna [Fecha Movimiento].

Quiero agradecerte que hayas posteado la informacion necesaria, que nos
permite relacionarnos mejor con tu problema y poder darte una sugerencia sin
tener que estar haciendo demasiadas preguntas. Este post es un ejemplo de que
se debe incluir en un mensaje, cuando pedimos ayuda para este tipo de
problemas.

AMB


"Danilo Reinoso" wrote:

Gracias Alejandro por tus sugerencias

Utilice la opcion de crear dos store procedure y de esta forma ya se ejecuta
mucho mas rapido.

Este es el store procedure que llama el anterior pasandole los dos
parametros.

CREATE PROCEDURE USP_Sum_FinScrap_By_Depto1 AS

SET NOCOUNT ON

DECLARE @DT_INI AS DATETIME
DECLARE @DT_FIN AS DATETIME
SET @DT_INI = (SELECT [Fecha Inicial] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)

EXEC dbo.USP_Sum_FinScrap_By_Depto @DT_INI, @DT_Fin
GO

una vez mas gracias por tu ayuda..


"Alejandro Mesa" wrote in message
news:
> Danilo Reinoso,
>
> Estas haciendo la prueba desde QA o SSMS directamente?
>
> Si es asi, te aconsejo que hagas la prueba creando un procedimiento
> almacenado, o que si insistes en hacerlo desde QA, que uses sp_executesql.
> Lo
> que pasa es que no usas parametros sino variables, que es diferente o que
> SQL
> Server emplea de forma diferente cuando estima la cardinalidad basada en
> el
> join y los filtros en la clausula where.
>
> Que pasa si haces:
>
> declare @sql nvarchar(4000)
> DECLARE @DT_INI AS DATETIME
> DECLARE @DT_FIN AS DATETIME
>
> SET @DT_INI = (SELECT [Fecha Inicial] FROM
> SVRSOLDATA.DBO.v_Datos_Reportes)
> SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
>
> set @sql = N'
> SELECT
> [Movido Desde],
> [Movido Hasta],
> [Item No],
> SUM([Cantidad Aceptada]) AS Total_Qty
> FROM
> dbo.Historial
> WHERE
> ([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
> AND ([Movido Hasta] = 'Scrap')
> GROUP BY
> [Movido Desde],
> [Movido Hasta],
> [Item No]
> '
>
> exec sp_executesql @sql, N'@DT_INI datetime, @DT_FIN datetime', @DT_INI,
> @DT_FIN
> GO
>
> Si lo vas a hacer con us sp, tendras que usar la opcion "OPTION
> (RECOMPILE)"
> en la sentencia select para que recompile la sentencia durante la
> ejecucion
> y pueda usar los valores de las variables para estimar cardinalidad, lo
> malo
> es que el plan de ejecucion de esta sentencia no se reusara. Tambien
> puedespartir el sp en dos, poniendo la ultima sentencia select en un sp
> por
> separado para que este sea llamado por un sp que assigna primero los
> valores
> a las variables @DT_INI y @DT_FIN y luego usa estas variables para pasar
> valores a los parametros de entrada de el segundo sp. Esto se debe a que
> durante la compilacion, SQL Server no sabe los valores de las variables,
> por
> lo que no puede hacer un estimado correecto de la cardinalidad y uso otro
> mecanismo para ello.
>
> create dbo.usp_p1
> @DT_INI datetime,
> @DT_FIN datetime
> as
> set nocount on
>
> SELECT
> [Movido Desde],
> [Movido Hasta],
> [Item No],
> SUM([Cantidad Aceptada]) AS Total_Qty
> FROM
> dbo.Historial
> WHERE
> ([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
> AND ([Movido Hasta] = 'Scrap')
> GROUP BY
> [Movido Desde],
> [Movido Hasta],
> [Item No]
> GO
>
> create dbo.usp_p2
> as
> set nocount on
>
> DECLARE @DT_INI AS DATETIME
> DECLARE @DT_FIN AS DATETIME
>
> SET @DT_INI = (SELECT [Fecha Inicial] FROM
> SVRSOLDATA.DBO.v_Datos_Reportes)
> SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
>
> exec dbo.usp_p1 @DT_INI, @DT_FIN
> GO
>
> EXEC dbo.usp_p2
> GO
>
> o puedes hacer lo sgte, si usas SS 2005 / 2008.
>
> create dbo.usp_p1
> as
> set nocount on
>
> DECLARE @DT_INI AS DATETIME
> DECLARE @DT_FIN AS DATETIME
>
> SET @DT_INI = (SELECT [Fecha Inicial] FROM
> SVRSOLDATA.DBO.v_Datos_Reportes)
> SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
>
> SELECT
> [Movido Desde],
> [Movido Hasta],
> [Item No],
> SUM([Cantidad Aceptada]) AS Total_Qty
> FROM
> dbo.Historial
> WHERE
> ([Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN)
> AND ([Movido Hasta] = 'Scrap')
> GROUP BY
> [Movido Desde],
> [Movido Hasta],
> [Item No]
> OPTION (RECOMPILE)
> GO
>
>
> AMB
>
> "Danilo Reinoso" wrote:
>
>> Saludos
>>
>> Utilizo SQL-Server 2000
>>
>> tengo el siguiente query el cual cuando le pongo los parametros declarado
>> tarda mas de lo normal unos 25 seg,
>> y cuando le pongo los parametros directo tarda menos 0.02 seg.
>> Lo que puedo observar es que cuando utilizo los parametros declarado la
>> consulta hace un index scan, y cuando lo pongo
>> directo hace un seek sobre el campo [Fecha Movimiento].
>> Como podria corregir el query para que cuando use los parametros me pueda
>> usar el index del campo [Fecha Movimiento].
>>
>> Este es el query:
>>
>> DECLARE @DT_INI AS DATETIME
>> DECLARE @DT_FIN AS DATETIME
>> SET @DT_INI = (SELECT [Fecha Inicial] FROM
>> SVRSOLDATA.DBO.v_Datos_Reportes)
>> SET @DT_FIN = (SELECT [Fecha Final] FROM SVRSOLDATA.DBO.v_Datos_Reportes)
>>
>>
>>
>>
>> SELECT dbo.Historial.[Movido Desde],
>> dbo.Historial.[Movido Hasta],
>> dbo.Historial.[Item No],
>> SUM(dbo.Historial.[Cantidad Aceptada]) AS Total_Qty
>> FROM dbo.Historial
>> WHERE (dbo.Historial.[Fecha Movimiento] BETWEEN @DT_INI AND @DT_FIN) --
>> '20081124' AND '20081124')
>> AND (dbo.Historial.[Movido Hasta] = 'Scrap')
>> GROUP BY dbo.Historial.[Movido Desde], dbo.Historial.[Movido Hasta],
>> dbo.Historial.[Item No]
>>
>>
>> ********************
>> scripts de la tabla historial
>> ********************
>>
>> if exists (select * from dbo.sysobjects where id > >> object_id(N'[dbo].[Historial]') and OBJECTPROPERTY(id, N'IsUserTable') =
>> 1)
>> drop table [dbo].[Historial]
>> GO
>>
>> CREATE TABLE [dbo].[Historial] (
>> [Transaccion] [int] NOT NULL ,
>> [Numero Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
>> NULL ,
>> [Movido Desde] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
>> ,
>> [Movido Hasta] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
>> ,
>> [Fecha Movimiento] [datetime] NULL ,
>> [Hora Movimiento] [datetime] COLLATE SQL_Latin1_General_CP1_CI_AS NULL
>> ,
>> [Item No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
>> [Item Descripcion] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
>> NULL
>> ,
>> [Cantidad Aceptada] [float] NULL ,
>> [Peso Aceptada] [float] NULL ,
>> [Cantidad Rechazada] [float] NULL ,
>> [Peso Rechazada] [float] NULL ,
>> [Cantidad Dañada] [float] NULL ,
>> [Peso Dañada] [float] NULL ,
>> [Peso Piedras] [float] NULL ,
>> [Peso Extra] [float] NULL ,
>> [Descripcion Extra] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
>> NULL ,
>> [Peso Salida] [float] NULL ,
>> [Total Orden] [float] NULL ,
>> [Total Peso] [float] NULL ,
>> [Direccion Foto] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
>> NULL ,
>> [Ultimo_Trabajo] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
>> NULL ,
>> [Empleado No] [int] NULL ,
>> [Empleado Nombre] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
>> NULL
>> ,
>> [Operacion No] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
>> ,
>> [Notas] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
>> [Notas_Mov] [varchar] (100) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
>> [Declarado] [bit] NULL ,
>> [Duracion] [float] NULL ,
>> [Usuario Sistema] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS
>> NULL
>> ,
>> [Status] [int] NULL
>> ) ON [PRIMARY]
>> GO
>>
>> ALTER TABLE [dbo].[Historial] WITH NOCHECK ADD
>> CONSTRAINT [PK__Historial__2B3F6F97] PRIMARY KEY CLUSTERED
>> (
>> [Transaccion]
>> ) ON [PRIMARY]
>> GO
>>
>> CREATE INDEX [IndicePorItemNo] ON [dbo].[Historial]([Item No]) ON
>> [PRIMARY]
>> GO
>>
>> CREATE INDEX [IndicePorNumeroTrabajo] ON [dbo].[Historial]([Numero
>> Trabajo]) ON [PRIMARY]
>> GO
>>
>> CREATE INDEX [IndicePorMovidoDesde] ON [dbo].[Historial]([Movido
>> Desde])
>> ON [PRIMARY]
>> GO
>>
>> CREATE INDEX [IndicePorMovidoHasta] ON [dbo].[Historial]([Movido
>> Hasta])
>> ON [PRIMARY]
>> GO
>>
>> CREATE INDEX [IndicePorFechaMovimiento] ON [dbo].[Historial]([Fecha
>> Movimiento]) ON [PRIMARY]
>> GO
>>
>> CREATE INDEX [IndicePorEmpleadoNo] ON [dbo].[Historial]([Empleado No])
>> ON
>> [PRIMARY]
>> GO
>>
>> CREATE INDEX [IndicePorOperacionNo] ON [dbo].[Historial]([Operacion
>> No])
>> ON [PRIMARY]
>> GO
>>
>> CREATE INDEX [Indice_Ultimo_Trabajo] ON
>> [dbo].[Historial]([Ultimo_Trabajo]) ON [PRIMARY]
>> GO
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una preguntaRespuesta Tengo una respuesta
Search Busqueda sugerida