Como elimino el cursor

03/05/2006 - 21:27 por Horacio | Informe spam
Hola,

Primero les comento cual es la necesidad y como la resolvimos:

Tenemos que guardar los datos provenientes de distintas fuentes, estos datos
estan compuesto por clave (codTag), valor, fechaHora (momento en que se
genero el dato, no momento de insercion), y un valor de alarma que no nos
interesa.

La tabla tiene esta estructura:

CREATE TABLE [dbo].[ValoresHistoricos] (
[codTag] [smallint] NOT NULL ,
[valor] [float] NULL ,
[fechaHora] [datetime] NOT NULL ,
[alarma] [varchar] (6) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]

Se permite null en el campo valor porque tiene un significado especial para
la aplicacion.

El tema es que ahora necesitamos calcular datos como un promedio ponderado
en el tiempo. Por ej (olvidandonos del campo alarma):

codTag Valor FechaHora
1, 400, '1/1/1 00:00:00'
1, 200, '1/1/1 00:10:00'
1, 150, '1/1/1 00:30:00'
1, 100, '1/1/1 01:10:00'

el promedio ponderado en el tiempo para el codTag = 1 es:
400 * 10 minutos (son 10 minutos porque ese es el tiempo que duro en ese
valor)
+
200 * 20
+
150*40
000
Todo dividido 70 minutos
0 (este es el promedio ponderado en el tiempo para este codTag en ese
periodo)
La pregunta es:
¿Se puede obtener este resultado sin recurrir a un cursor como actualmente
se hace?

¿Es necesario proponer otra estructura en la tabla para mejorar el
rendimiento y evitar el cursor?

Hemos intentado hacer algo diferente precalculando valores mediante
triggers, pero se complica porque los datos pueden llegar a entrar
desordenados cronologicamente. Ejemplo, hoy pueden estar entrendo datos
actuales y datos de ayer para el mismo codTag.

Cualquier otra informacion que necesiten no duden en solicitarla.

Muchas gracias por su tiempo.

Saludos

Horacio

Preguntas similare

Leer las respuestas

#6 Alejandro Mesa
04/05/2006 - 15:22 | Informe spam
Horacio,

Cambie una referencia que estava incorrecta

select
a.codTag,
sum(a.valor * datediff(minute, a.fechaHora, b.fechaHora)) /
sum(datediff(minute, a.fechaHora, b.fechaHora))
from
[dbo].[ValoresHistoricos] as a
inner join
[dbo].[ValoresHistoricos] as b
on b.codTag = a.codTag
and b.fechaHora = (
select min(c.fechaHora)
from [dbo].[ValoresHistoricos] as c
where
c.codTag = a.codTag -- AQUI FUE EL CAMBIO
and c.fechaHora > a.fechaHora
)
group by
a.codTag
go


AMB

"Horacio" wrote:

Que curioso...

El codTag 11111 lo genere para esta prueba. Y la alarma definitivamente no
influye.

Si creo una tabla nueva con solo esos datos, sí funciona, pero en cuanto
agrego datos deja comienza a fallar.

Te paso este nuevo pack de datos, el resultado debe ser el mismo para cada
codtag

insert into ValoresHistoricos2 values(11111,350,'May 3 2006 12:00AM ','NADA')
insert into ValoresHistoricos2 values(11111,150,'May 3 2006 12:10AM ','NADA')
insert into ValoresHistoricos2 values(11111,400,'May 3 2006 12:40AM ','NADA')
insert into ValoresHistoricos2 values(11111,200,'May 3 2006 1:10AM ','NADA')
insert into ValoresHistoricos2 values(11111,250,'May 3 2006 1:30AM ','NADA')
insert into ValoresHistoricos2 values(11112,350,'May 3 2006 12:10AM ','NADA')
insert into ValoresHistoricos2 values(11112,150,'May 3 2006 12:20AM ','NADA')
insert into ValoresHistoricos2 values(11112,400,'May 3 2006 12:50AM ','NADA')
insert into ValoresHistoricos2 values(11112,200,'May 3 2006 1:20AM ','NADA')
insert into ValoresHistoricos2 values(11112,250,'May 3 2006 1:40AM ','NADA')
insert into ValoresHistoricos2 values(11113,350,'May 3 2006 12:20AM ','NADA')
insert into ValoresHistoricos2 values(11113,150,'May 3 2006 12:30AM ','NADA')
insert into ValoresHistoricos2 values(11114,400,'May 3 2006 1:10AM ','NADA')
insert into ValoresHistoricos2 values(11114,200,'May 3 2006 1:40AM ','NADA')
insert into ValoresHistoricos2 values(11114,250,'May 3 2006 2:00AM ','NADA')
insert into ValoresHistoricos2 values(11114,350,'May 3 2006 12:30AM ','NADA')
insert into ValoresHistoricos2 values(11114,150,'May 3 2006 12:40AM ','NADA')
insert into ValoresHistoricos2 values(11113,400,'May 3 2006 1:00AM ','NADA')
insert into ValoresHistoricos2 values(11113,200,'May 3 2006 1:30AM ','NADA')
insert into ValoresHistoricos2 values(11113,250,'May 3 2006 1:50AM ','NADA')

Muchas gracias

"Alejandro Mesa" wrote:

> Horacio,
>
> Estas seguro que la alarma no es importante en este calculo?. Chequea a ver
> cuantas filas existen en tu tabla donde codTag = 11111. Cuando ejecuto la
> sentencia en mi maquina solo con el grupo que me distes, este es el resultado:
>
> codTag
> 11111 266.66666666666669
>
> (1 row(s) affected)
>
>
> En cuanto a los indices, no tengo informacion suficiente como para decirte
> cuales si y cuales no, pero pudieras empezar por decirnos cual es la clave
> primaria de esa tabla. Pudieras empezar con:
>
> create clustered index ValoresHistoricos_fechaHora_nu_c_idx
> on [dbo].[ValoresHistoricos] (fechaHora)
> go
>
> create nonclustered index ValoresHistoricos_codTag_nu_nc_idx
> on [dbo].[ValoresHistoricos] (codTag)
> go
>
>
> AMB
>
> "Horacio" wrote:
>
> > Gracias por tu respuesta Alejandro!
> >
> > Con este pack de datos deveria dar 266,66, pero obtengo 320 con tu solución.
> >
> > insert into valoreshistoricos values (11111,350, '20060503 00:00','HRC')
> > insert into valoreshistoricos values (11111,150, '20060503 00:10','HRC')
> > insert into valoreshistoricos values (11111,400, '20060503 00:40','HRC')
> > insert into valoreshistoricos values (11111,200, '20060503 01:10','HRC')
> > insert into valoreshistoricos values (11111,250, '20060503 01:30','HRC')
> >
> > Conste que yo le agrege:
> >
> > having a.codtag111
> >
> > al final de la consulta.
> >
> > De todas formas, si la solución viene por este lado, que indices me
> > recomendas modificar para obtener un mejor rendimiento.
> >
> > Saludos
> >
> > Horacio
> >
> >
> > "Alejandro Mesa" escribió:
> >
> > > Trata,
> > >
> > > select
> > > a.codTag, sum(a.valor * datediff(minute, a.fechaHora, b.fechaHora)) /
> > > datediff(minute, min(a.fechaHora), max(b.fechaHora))
> > > from
> > > [dbo].[ValoresHistoricos] as a
> > > inner join
> > > [dbo].[ValoresHistoricos] as b
> > > on b.codTag = a.codTag
> > > and b.fechaHora = (select min(c.fechaHora) from [dbo].[ValoresHistoricos]
> > > as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)
> > > group by
> > > a.codTag
> > > go
> > >
> > >
> > > AMB
> > >
> > > "Horacio" wrote:
> > >
> > > > Hola,
> > > >
> > > > Primero les comento cual es la necesidad y como la resolvimos:
> > > >
> > > > Tenemos que guardar los datos provenientes de distintas fuentes, estos datos
> > > > estan compuesto por clave (codTag), valor, fechaHora (momento en que se
> > > > genero el dato, no momento de insercion), y un valor de alarma que no nos
> > > > interesa.
> > > >
> > > > La tabla tiene esta estructura:
> > > >
> > > > CREATE TABLE [dbo].[ValoresHistoricos] (
> > > > [codTag] [smallint] NOT NULL ,
> > > > [valor] [float] NULL ,
> > > > [fechaHora] [datetime] NOT NULL ,
> > > > [alarma] [varchar] (6) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
> > > > ) ON [PRIMARY]
> > > >
> > > > Se permite null en el campo valor porque tiene un significado especial para
> > > > la aplicacion.
> > > >
> > > > El tema es que ahora necesitamos calcular datos como un promedio ponderado
> > > > en el tiempo. Por ej (olvidandonos del campo alarma):
> > > >
> > > > codTag Valor FechaHora
> > > > 1, 400, '1/1/1 00:00:00'
> > > > 1, 200, '1/1/1 00:10:00'
> > > > 1, 150, '1/1/1 00:30:00'
> > > > 1, 100, '1/1/1 01:10:00'
> > > >
> > > > el promedio ponderado en el tiempo para el codTag = 1 es:
> > > > 400 * 10 minutos (son 10 minutos porque ese es el tiempo que duro en ese
> > > > valor)
> > > > +
> > > > 200 * 20
> > > > +
> > > > 150*40
> > > > 000
> > > > Todo dividido 70 minutos
> > > > 0 (este es el promedio ponderado en el tiempo para este codTag en ese
> > > > periodo)
> > > > La pregunta es:
> > > > ¿Se puede obtener este resultado sin recurrir a un cursor como actualmente
> > > > se hace?
> > > >
> > > > ¿Es necesario proponer otra estructura en la tabla para mejorar el
> > > > rendimiento y evitar el cursor?
> > > >
> > > > Hemos intentado hacer algo diferente precalculando valores mediante
> > > > triggers, pero se complica porque los datos pueden llegar a entrar
> > > > desordenados cronologicamente. Ejemplo, hoy pueden estar entrendo datos
> > > > actuales y datos de ayer para el mismo codTag.
> > > >
> > > > Cualquier otra informacion que necesiten no duden en solicitarla.
> > > >
> > > > Muchas gracias por su tiempo.
> > > >
> > > > Saludos
> > > >
> > > > Horacio
> > > >
> > > >
Respuesta Responder a este mensaje
#7 Alejandro Mesa
04/05/2006 - 15:28 | Informe spam
Horacio,

Esta correcto el cambio que hicistes (lee mi otro mensaje).

Te explico como funciona la cosa. Estoy uniendo la tabla consigo misma,
machando cada fila con la fila inmediata.

Ejemplo:

values(11111,350,'May 3 2006 12:00AM ','NADA')

se une con

values(11111,150,'May 3 2006 12:10AM ','NADA')

que es la que le sigue de acuerdo a codTag y fechaHora. Como sabemos cual es
la fila inmediata?. La fila inmediata es aquella con igual codTag y cuya
fechaHora es igual a la menos de las fechaHora que son mayores a la fechaHora
que se esta procesando en la primera referencia a la tabla.


AMB


"Horacio" wrote:

Ahora si.

Agregue
and a.codtag=c.codtag
En:
(select min(c.fechaHora) from [dbo].[ValoresHistoricos2]
as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)

Y ahora funciona.

Me puedo quedar tranquilo con esta solución? Se te ocurre alguna otra prueba
para verificar el resultado?

Te soy sincero, lo puse ahi porque me parecio logico, pero no estoy seguro
de comprender como funciona la consulta. Y está claro que nunca hubiera
llegado a esa solución.

Muchas gracias


"Horacio" wrote:

> Que curioso...
>
> El codTag 11111 lo genere para esta prueba. Y la alarma definitivamente no
> influye.
>
> Si creo una tabla nueva con solo esos datos, sí funciona, pero en cuanto
> agrego datos deja comienza a fallar.
>
> Te paso este nuevo pack de datos, el resultado debe ser el mismo para cada
> codtag
>
> insert into ValoresHistoricos2 values(11111,350,'May 3 2006 12:00AM ','NADA')
> insert into ValoresHistoricos2 values(11111,150,'May 3 2006 12:10AM ','NADA')
> insert into ValoresHistoricos2 values(11111,400,'May 3 2006 12:40AM ','NADA')
> insert into ValoresHistoricos2 values(11111,200,'May 3 2006 1:10AM ','NADA')
> insert into ValoresHistoricos2 values(11111,250,'May 3 2006 1:30AM ','NADA')
> insert into ValoresHistoricos2 values(11112,350,'May 3 2006 12:10AM ','NADA')
> insert into ValoresHistoricos2 values(11112,150,'May 3 2006 12:20AM ','NADA')
> insert into ValoresHistoricos2 values(11112,400,'May 3 2006 12:50AM ','NADA')
> insert into ValoresHistoricos2 values(11112,200,'May 3 2006 1:20AM ','NADA')
> insert into ValoresHistoricos2 values(11112,250,'May 3 2006 1:40AM ','NADA')
> insert into ValoresHistoricos2 values(11113,350,'May 3 2006 12:20AM ','NADA')
> insert into ValoresHistoricos2 values(11113,150,'May 3 2006 12:30AM ','NADA')
> insert into ValoresHistoricos2 values(11114,400,'May 3 2006 1:10AM ','NADA')
> insert into ValoresHistoricos2 values(11114,200,'May 3 2006 1:40AM ','NADA')
> insert into ValoresHistoricos2 values(11114,250,'May 3 2006 2:00AM ','NADA')
> insert into ValoresHistoricos2 values(11114,350,'May 3 2006 12:30AM ','NADA')
> insert into ValoresHistoricos2 values(11114,150,'May 3 2006 12:40AM ','NADA')
> insert into ValoresHistoricos2 values(11113,400,'May 3 2006 1:00AM ','NADA')
> insert into ValoresHistoricos2 values(11113,200,'May 3 2006 1:30AM ','NADA')
> insert into ValoresHistoricos2 values(11113,250,'May 3 2006 1:50AM ','NADA')
>
> Muchas gracias
>
> "Alejandro Mesa" wrote:
>
> > Horacio,
> >
> > Estas seguro que la alarma no es importante en este calculo?. Chequea a ver
> > cuantas filas existen en tu tabla donde codTag = 11111. Cuando ejecuto la
> > sentencia en mi maquina solo con el grupo que me distes, este es el resultado:
> >
> > codTag
> > 11111 266.66666666666669
> >
> > (1 row(s) affected)
> >
> >
> > En cuanto a los indices, no tengo informacion suficiente como para decirte
> > cuales si y cuales no, pero pudieras empezar por decirnos cual es la clave
> > primaria de esa tabla. Pudieras empezar con:
> >
> > create clustered index ValoresHistoricos_fechaHora_nu_c_idx
> > on [dbo].[ValoresHistoricos] (fechaHora)
> > go
> >
> > create nonclustered index ValoresHistoricos_codTag_nu_nc_idx
> > on [dbo].[ValoresHistoricos] (codTag)
> > go
> >
> >
> > AMB
> >
> > "Horacio" wrote:
> >
> > > Gracias por tu respuesta Alejandro!
> > >
> > > Con este pack de datos deveria dar 266,66, pero obtengo 320 con tu solución.
> > >
> > > insert into valoreshistoricos values (11111,350, '20060503 00:00','HRC')
> > > insert into valoreshistoricos values (11111,150, '20060503 00:10','HRC')
> > > insert into valoreshistoricos values (11111,400, '20060503 00:40','HRC')
> > > insert into valoreshistoricos values (11111,200, '20060503 01:10','HRC')
> > > insert into valoreshistoricos values (11111,250, '20060503 01:30','HRC')
> > >
> > > Conste que yo le agrege:
> > >
> > > having a.codtag111
> > >
> > > al final de la consulta.
> > >
> > > De todas formas, si la solución viene por este lado, que indices me
> > > recomendas modificar para obtener un mejor rendimiento.
> > >
> > > Saludos
> > >
> > > Horacio
> > >
> > >
> > > "Alejandro Mesa" escribió:
> > >
> > > > Trata,
> > > >
> > > > select
> > > > a.codTag, sum(a.valor * datediff(minute, a.fechaHora, b.fechaHora)) /
> > > > datediff(minute, min(a.fechaHora), max(b.fechaHora))
> > > > from
> > > > [dbo].[ValoresHistoricos] as a
> > > > inner join
> > > > [dbo].[ValoresHistoricos] as b
> > > > on b.codTag = a.codTag
> > > > and b.fechaHora = (select min(c.fechaHora) from [dbo].[ValoresHistoricos]
> > > > as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)
> > > > group by
> > > > a.codTag
> > > > go
> > > >
> > > >
> > > > AMB
> > > >
> > > > "Horacio" wrote:
> > > >
> > > > > Hola,
> > > > >
> > > > > Primero les comento cual es la necesidad y como la resolvimos:
> > > > >
> > > > > Tenemos que guardar los datos provenientes de distintas fuentes, estos datos
> > > > > estan compuesto por clave (codTag), valor, fechaHora (momento en que se
> > > > > genero el dato, no momento de insercion), y un valor de alarma que no nos
> > > > > interesa.
> > > > >
> > > > > La tabla tiene esta estructura:
> > > > >
> > > > > CREATE TABLE [dbo].[ValoresHistoricos] (
> > > > > [codTag] [smallint] NOT NULL ,
> > > > > [valor] [float] NULL ,
> > > > > [fechaHora] [datetime] NOT NULL ,
> > > > > [alarma] [varchar] (6) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
> > > > > ) ON [PRIMARY]
> > > > >
> > > > > Se permite null en el campo valor porque tiene un significado especial para
> > > > > la aplicacion.
> > > > >
> > > > > El tema es que ahora necesitamos calcular datos como un promedio ponderado
> > > > > en el tiempo. Por ej (olvidandonos del campo alarma):
> > > > >
> > > > > codTag Valor FechaHora
> > > > > 1, 400, '1/1/1 00:00:00'
> > > > > 1, 200, '1/1/1 00:10:00'
> > > > > 1, 150, '1/1/1 00:30:00'
> > > > > 1, 100, '1/1/1 01:10:00'
> > > > >
> > > > > el promedio ponderado en el tiempo para el codTag = 1 es:
> > > > > 400 * 10 minutos (son 10 minutos porque ese es el tiempo que duro en ese
> > > > > valor)
> > > > > +
> > > > > 200 * 20
> > > > > +
> > > > > 150*40
> > > > > 000
> > > > > Todo dividido 70 minutos
> > > > > 0 (este es el promedio ponderado en el tiempo para este codTag en ese
> > > > > periodo)
> > > > > La pregunta es:
> > > > > ¿Se puede obtener este resultado sin recurrir a un cursor como actualmente
> > > > > se hace?
> > > > >
> > > > > ¿Es necesario proponer otra estructura en la tabla para mejorar el
> > > > > rendimiento y evitar el cursor?
> > > > >
> > > > > Hemos intentado hacer algo diferente precalculando valores mediante
> > > > > triggers, pero se complica porque los datos pueden llegar a entrar
> > > > > desordenados cronologicamente. Ejemplo, hoy pueden estar entrendo datos
> > > > > actuales y datos de ayer para el mismo codTag.
> > > > >
> > > > > Cualquier otra informacion que necesiten no duden en solicitarla.
> > > > >
> > > > > Muchas gracias por su tiempo.
> > > > >
> > > > > Saludos
> > > > >
> > > > > Horacio
> > > > >
> > > > >
Respuesta Responder a este mensaje
#8 Horacio
04/05/2006 - 16:23 | Informe spam
Bien, está claro. Aunque me cuesta asimilarlo.

Volviendo al tema de los indices.
Cuando hago la consulta sobre la tabla con unos cuantos millones de
registros, el execution plan me tira que el 99% del "costo" de la consulta
esta sobre el "clustered index seek" en valores historicos. Estas son buenas
noticias, verdad? o tiene otra lectura?



"Alejandro Mesa" wrote:

Horacio,

Esta correcto el cambio que hicistes (lee mi otro mensaje).

Te explico como funciona la cosa. Estoy uniendo la tabla consigo misma,
machando cada fila con la fila inmediata.

Ejemplo:

values(11111,350,'May 3 2006 12:00AM ','NADA')

se une con

values(11111,150,'May 3 2006 12:10AM ','NADA')

que es la que le sigue de acuerdo a codTag y fechaHora. Como sabemos cual es
la fila inmediata?. La fila inmediata es aquella con igual codTag y cuya
fechaHora es igual a la menos de las fechaHora que son mayores a la fechaHora
que se esta procesando en la primera referencia a la tabla.


AMB


"Horacio" wrote:

> Ahora si.
>
> Agregue
> and a.codtag=c.codtag
> En:
> (select min(c.fechaHora) from [dbo].[ValoresHistoricos2]
> as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)
>
> Y ahora funciona.
>
> Me puedo quedar tranquilo con esta solución? Se te ocurre alguna otra prueba
> para verificar el resultado?
>
> Te soy sincero, lo puse ahi porque me parecio logico, pero no estoy seguro
> de comprender como funciona la consulta. Y está claro que nunca hubiera
> llegado a esa solución.
>
> Muchas gracias
>
>
> "Horacio" wrote:
>
> > Que curioso...
> >
> > El codTag 11111 lo genere para esta prueba. Y la alarma definitivamente no
> > influye.
> >
> > Si creo una tabla nueva con solo esos datos, sí funciona, pero en cuanto
> > agrego datos deja comienza a fallar.
> >
> > Te paso este nuevo pack de datos, el resultado debe ser el mismo para cada
> > codtag
> >
> > insert into ValoresHistoricos2 values(11111,350,'May 3 2006 12:00AM ','NADA')
> > insert into ValoresHistoricos2 values(11111,150,'May 3 2006 12:10AM ','NADA')
> > insert into ValoresHistoricos2 values(11111,400,'May 3 2006 12:40AM ','NADA')
> > insert into ValoresHistoricos2 values(11111,200,'May 3 2006 1:10AM ','NADA')
> > insert into ValoresHistoricos2 values(11111,250,'May 3 2006 1:30AM ','NADA')
> > insert into ValoresHistoricos2 values(11112,350,'May 3 2006 12:10AM ','NADA')
> > insert into ValoresHistoricos2 values(11112,150,'May 3 2006 12:20AM ','NADA')
> > insert into ValoresHistoricos2 values(11112,400,'May 3 2006 12:50AM ','NADA')
> > insert into ValoresHistoricos2 values(11112,200,'May 3 2006 1:20AM ','NADA')
> > insert into ValoresHistoricos2 values(11112,250,'May 3 2006 1:40AM ','NADA')
> > insert into ValoresHistoricos2 values(11113,350,'May 3 2006 12:20AM ','NADA')
> > insert into ValoresHistoricos2 values(11113,150,'May 3 2006 12:30AM ','NADA')
> > insert into ValoresHistoricos2 values(11114,400,'May 3 2006 1:10AM ','NADA')
> > insert into ValoresHistoricos2 values(11114,200,'May 3 2006 1:40AM ','NADA')
> > insert into ValoresHistoricos2 values(11114,250,'May 3 2006 2:00AM ','NADA')
> > insert into ValoresHistoricos2 values(11114,350,'May 3 2006 12:30AM ','NADA')
> > insert into ValoresHistoricos2 values(11114,150,'May 3 2006 12:40AM ','NADA')
> > insert into ValoresHistoricos2 values(11113,400,'May 3 2006 1:00AM ','NADA')
> > insert into ValoresHistoricos2 values(11113,200,'May 3 2006 1:30AM ','NADA')
> > insert into ValoresHistoricos2 values(11113,250,'May 3 2006 1:50AM ','NADA')
> >
> > Muchas gracias
> >
> > "Alejandro Mesa" wrote:
> >
> > > Horacio,
> > >
> > > Estas seguro que la alarma no es importante en este calculo?. Chequea a ver
> > > cuantas filas existen en tu tabla donde codTag = 11111. Cuando ejecuto la
> > > sentencia en mi maquina solo con el grupo que me distes, este es el resultado:
> > >
> > > codTag
> > > 11111 266.66666666666669
> > >
> > > (1 row(s) affected)
> > >
> > >
> > > En cuanto a los indices, no tengo informacion suficiente como para decirte
> > > cuales si y cuales no, pero pudieras empezar por decirnos cual es la clave
> > > primaria de esa tabla. Pudieras empezar con:
> > >
> > > create clustered index ValoresHistoricos_fechaHora_nu_c_idx
> > > on [dbo].[ValoresHistoricos] (fechaHora)
> > > go
> > >
> > > create nonclustered index ValoresHistoricos_codTag_nu_nc_idx
> > > on [dbo].[ValoresHistoricos] (codTag)
> > > go
> > >
> > >
> > > AMB
> > >
> > > "Horacio" wrote:
> > >
> > > > Gracias por tu respuesta Alejandro!
> > > >
> > > > Con este pack de datos deveria dar 266,66, pero obtengo 320 con tu solución.
> > > >
> > > > insert into valoreshistoricos values (11111,350, '20060503 00:00','HRC')
> > > > insert into valoreshistoricos values (11111,150, '20060503 00:10','HRC')
> > > > insert into valoreshistoricos values (11111,400, '20060503 00:40','HRC')
> > > > insert into valoreshistoricos values (11111,200, '20060503 01:10','HRC')
> > > > insert into valoreshistoricos values (11111,250, '20060503 01:30','HRC')
> > > >
> > > > Conste que yo le agrege:
> > > >
> > > > having a.codtag111
> > > >
> > > > al final de la consulta.
> > > >
> > > > De todas formas, si la solución viene por este lado, que indices me
> > > > recomendas modificar para obtener un mejor rendimiento.
> > > >
> > > > Saludos
> > > >
> > > > Horacio
> > > >
> > > >
> > > > "Alejandro Mesa" escribió:
> > > >
> > > > > Trata,
> > > > >
> > > > > select
> > > > > a.codTag, sum(a.valor * datediff(minute, a.fechaHora, b.fechaHora)) /
> > > > > datediff(minute, min(a.fechaHora), max(b.fechaHora))
> > > > > from
> > > > > [dbo].[ValoresHistoricos] as a
> > > > > inner join
> > > > > [dbo].[ValoresHistoricos] as b
> > > > > on b.codTag = a.codTag
> > > > > and b.fechaHora = (select min(c.fechaHora) from [dbo].[ValoresHistoricos]
> > > > > as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)
> > > > > group by
> > > > > a.codTag
> > > > > go
> > > > >
> > > > >
> > > > > AMB
> > > > >
> > > > > "Horacio" wrote:
> > > > >
> > > > > > Hola,
> > > > > >
> > > > > > Primero les comento cual es la necesidad y como la resolvimos:
> > > > > >
> > > > > > Tenemos que guardar los datos provenientes de distintas fuentes, estos datos
> > > > > > estan compuesto por clave (codTag), valor, fechaHora (momento en que se
> > > > > > genero el dato, no momento de insercion), y un valor de alarma que no nos
> > > > > > interesa.
> > > > > >
> > > > > > La tabla tiene esta estructura:
> > > > > >
> > > > > > CREATE TABLE [dbo].[ValoresHistoricos] (
> > > > > > [codTag] [smallint] NOT NULL ,
> > > > > > [valor] [float] NULL ,
> > > > > > [fechaHora] [datetime] NOT NULL ,
> > > > > > [alarma] [varchar] (6) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
> > > > > > ) ON [PRIMARY]
> > > > > >
> > > > > > Se permite null en el campo valor porque tiene un significado especial para
> > > > > > la aplicacion.
> > > > > >
> > > > > > El tema es que ahora necesitamos calcular datos como un promedio ponderado
> > > > > > en el tiempo. Por ej (olvidandonos del campo alarma):
> > > > > >
> > > > > > codTag Valor FechaHora
> > > > > > 1, 400, '1/1/1 00:00:00'
> > > > > > 1, 200, '1/1/1 00:10:00'
> > > > > > 1, 150, '1/1/1 00:30:00'
> > > > > > 1, 100, '1/1/1 01:10:00'
> > > > > >
> > > > > > el promedio ponderado en el tiempo para el codTag = 1 es:
> > > > > > 400 * 10 minutos (son 10 minutos porque ese es el tiempo que duro en ese
> > > > > > valor)
> > > > > > +
> > > > > > 200 * 20
> > > > > > +
> > > > > > 150*40
> > > > > > 000
> > > > > > Todo dividido 70 minutos
> > > > > > 0 (este es el promedio ponderado en el tiempo para este codTag en ese
> > > > > > periodo)
> > > > > > La pregunta es:
> > > > > > ¿Se puede obtener este resultado sin recurrir a un cursor como actualmente
> > > > > > se hace?
> > > > > >
> > > > > > ¿Es necesario proponer otra estructura en la tabla para mejorar el
> > > > > > rendimiento y evitar el cursor?
> > > > > >
> > > > > > Hemos intentado hacer algo diferente precalculando valores mediante
> > > > > > triggers, pero se complica porque los datos pueden llegar a entrar
> > > > > > desordenados cronologicamente. Ejemplo, hoy pueden estar entrendo datos
> > > > > > actuales y datos de ayer para el mismo codTag.
> > > > > >
> > > > > > Cualquier otra informacion que necesiten no duden en solicitarla.
> > > > > >
> > > > > > Muchas gracias por su tiempo.
> > > > > >
> > > > > > Saludos
> > > > > >
> > > > > > Horacio
> > > > > >
> > > > > >
Respuesta Responder a este mensaje
#9 Alejandro Mesa
04/05/2006 - 16:34 | Informe spam
Horacio,

Cuando hago la consulta sobre la tabla con unos cuantos millones de
registros, el execution plan me tira que el 99% del "costo" de la consulta
esta sobre el "clustered index seek" en valores historicos.



Si la operacion es un "index seek" sobre el clustered index, entonces no me
preocuapria. Si el tiempo de respuesta esta dentro de las expectativas del
cliente, entonces podemos descansar por un tiempo.


AMB

"Horacio" wrote:

Bien, está claro. Aunque me cuesta asimilarlo.

Volviendo al tema de los indices.
Cuando hago la consulta sobre la tabla con unos cuantos millones de
registros, el execution plan me tira que el 99% del "costo" de la consulta
esta sobre el "clustered index seek" en valores historicos. Estas son buenas
noticias, verdad? o tiene otra lectura?



"Alejandro Mesa" wrote:

> Horacio,
>
> Esta correcto el cambio que hicistes (lee mi otro mensaje).
>
> Te explico como funciona la cosa. Estoy uniendo la tabla consigo misma,
> machando cada fila con la fila inmediata.
>
> Ejemplo:
>
> values(11111,350,'May 3 2006 12:00AM ','NADA')
>
> se une con
>
> values(11111,150,'May 3 2006 12:10AM ','NADA')
>
> que es la que le sigue de acuerdo a codTag y fechaHora. Como sabemos cual es
> la fila inmediata?. La fila inmediata es aquella con igual codTag y cuya
> fechaHora es igual a la menos de las fechaHora que son mayores a la fechaHora
> que se esta procesando en la primera referencia a la tabla.
>
>
> AMB
>
>
> "Horacio" wrote:
>
> > Ahora si.
> >
> > Agregue
> > and a.codtag=c.codtag
> > En:
> > (select min(c.fechaHora) from [dbo].[ValoresHistoricos2]
> > as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)
> >
> > Y ahora funciona.
> >
> > Me puedo quedar tranquilo con esta solución? Se te ocurre alguna otra prueba
> > para verificar el resultado?
> >
> > Te soy sincero, lo puse ahi porque me parecio logico, pero no estoy seguro
> > de comprender como funciona la consulta. Y está claro que nunca hubiera
> > llegado a esa solución.
> >
> > Muchas gracias
> >
> >
> > "Horacio" wrote:
> >
> > > Que curioso...
> > >
> > > El codTag 11111 lo genere para esta prueba. Y la alarma definitivamente no
> > > influye.
> > >
> > > Si creo una tabla nueva con solo esos datos, sí funciona, pero en cuanto
> > > agrego datos deja comienza a fallar.
> > >
> > > Te paso este nuevo pack de datos, el resultado debe ser el mismo para cada
> > > codtag
> > >
> > > insert into ValoresHistoricos2 values(11111,350,'May 3 2006 12:00AM ','NADA')
> > > insert into ValoresHistoricos2 values(11111,150,'May 3 2006 12:10AM ','NADA')
> > > insert into ValoresHistoricos2 values(11111,400,'May 3 2006 12:40AM ','NADA')
> > > insert into ValoresHistoricos2 values(11111,200,'May 3 2006 1:10AM ','NADA')
> > > insert into ValoresHistoricos2 values(11111,250,'May 3 2006 1:30AM ','NADA')
> > > insert into ValoresHistoricos2 values(11112,350,'May 3 2006 12:10AM ','NADA')
> > > insert into ValoresHistoricos2 values(11112,150,'May 3 2006 12:20AM ','NADA')
> > > insert into ValoresHistoricos2 values(11112,400,'May 3 2006 12:50AM ','NADA')
> > > insert into ValoresHistoricos2 values(11112,200,'May 3 2006 1:20AM ','NADA')
> > > insert into ValoresHistoricos2 values(11112,250,'May 3 2006 1:40AM ','NADA')
> > > insert into ValoresHistoricos2 values(11113,350,'May 3 2006 12:20AM ','NADA')
> > > insert into ValoresHistoricos2 values(11113,150,'May 3 2006 12:30AM ','NADA')
> > > insert into ValoresHistoricos2 values(11114,400,'May 3 2006 1:10AM ','NADA')
> > > insert into ValoresHistoricos2 values(11114,200,'May 3 2006 1:40AM ','NADA')
> > > insert into ValoresHistoricos2 values(11114,250,'May 3 2006 2:00AM ','NADA')
> > > insert into ValoresHistoricos2 values(11114,350,'May 3 2006 12:30AM ','NADA')
> > > insert into ValoresHistoricos2 values(11114,150,'May 3 2006 12:40AM ','NADA')
> > > insert into ValoresHistoricos2 values(11113,400,'May 3 2006 1:00AM ','NADA')
> > > insert into ValoresHistoricos2 values(11113,200,'May 3 2006 1:30AM ','NADA')
> > > insert into ValoresHistoricos2 values(11113,250,'May 3 2006 1:50AM ','NADA')
> > >
> > > Muchas gracias
> > >
> > > "Alejandro Mesa" wrote:
> > >
> > > > Horacio,
> > > >
> > > > Estas seguro que la alarma no es importante en este calculo?. Chequea a ver
> > > > cuantas filas existen en tu tabla donde codTag = 11111. Cuando ejecuto la
> > > > sentencia en mi maquina solo con el grupo que me distes, este es el resultado:
> > > >
> > > > codTag
> > > > 11111 266.66666666666669
> > > >
> > > > (1 row(s) affected)
> > > >
> > > >
> > > > En cuanto a los indices, no tengo informacion suficiente como para decirte
> > > > cuales si y cuales no, pero pudieras empezar por decirnos cual es la clave
> > > > primaria de esa tabla. Pudieras empezar con:
> > > >
> > > > create clustered index ValoresHistoricos_fechaHora_nu_c_idx
> > > > on [dbo].[ValoresHistoricos] (fechaHora)
> > > > go
> > > >
> > > > create nonclustered index ValoresHistoricos_codTag_nu_nc_idx
> > > > on [dbo].[ValoresHistoricos] (codTag)
> > > > go
> > > >
> > > >
> > > > AMB
> > > >
> > > > "Horacio" wrote:
> > > >
> > > > > Gracias por tu respuesta Alejandro!
> > > > >
> > > > > Con este pack de datos deveria dar 266,66, pero obtengo 320 con tu solución.
> > > > >
> > > > > insert into valoreshistoricos values (11111,350, '20060503 00:00','HRC')
> > > > > insert into valoreshistoricos values (11111,150, '20060503 00:10','HRC')
> > > > > insert into valoreshistoricos values (11111,400, '20060503 00:40','HRC')
> > > > > insert into valoreshistoricos values (11111,200, '20060503 01:10','HRC')
> > > > > insert into valoreshistoricos values (11111,250, '20060503 01:30','HRC')
> > > > >
> > > > > Conste que yo le agrege:
> > > > >
> > > > > having a.codtag111
> > > > >
> > > > > al final de la consulta.
> > > > >
> > > > > De todas formas, si la solución viene por este lado, que indices me
> > > > > recomendas modificar para obtener un mejor rendimiento.
> > > > >
> > > > > Saludos
> > > > >
> > > > > Horacio
> > > > >
> > > > >
> > > > > "Alejandro Mesa" escribió:
> > > > >
> > > > > > Trata,
> > > > > >
> > > > > > select
> > > > > > a.codTag, sum(a.valor * datediff(minute, a.fechaHora, b.fechaHora)) /
> > > > > > datediff(minute, min(a.fechaHora), max(b.fechaHora))
> > > > > > from
> > > > > > [dbo].[ValoresHistoricos] as a
> > > > > > inner join
> > > > > > [dbo].[ValoresHistoricos] as b
> > > > > > on b.codTag = a.codTag
> > > > > > and b.fechaHora = (select min(c.fechaHora) from [dbo].[ValoresHistoricos]
> > > > > > as c where b.codTag = a.codTag and c.fechaHora > a.fechaHora)
> > > > > > group by
> > > > > > a.codTag
> > > > > > go
> > > > > >
> > > > > >
> > > > > > AMB
> > > > > >
> > > > > > "Horacio" wrote:
> > > > > >
> > > > > > > Hola,
> > > > > > >
> > > > > > > Primero les comento cual es la necesidad y como la resolvimos:
> > > > > > >
> > > > > > > Tenemos que guardar los datos provenientes de distintas fuentes, estos datos
> > > > > > > estan compuesto por clave (codTag), valor, fechaHora (momento en que se
> > > > > > > genero el dato, no momento de insercion), y un valor de alarma que no nos
> > > > > > > interesa.
> > > > > > >
> > > > > > > La tabla tiene esta estructura:
> > > > > > >
> > > > > > > CREATE TABLE [dbo].[ValoresHistoricos] (
> > > > > > > [codTag] [smallint] NOT NULL ,
> > > > > > > [valor] [float] NULL ,
> > > > > > > [fechaHora] [datetime] NOT NULL ,
> > > > > > > [alarma] [varchar] (6) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
> > > > > > > ) ON [PRIMARY]
> > > > > > >
> > > > > > > Se permite null en el campo valor porque tiene un significado especial para
> > > > > > > la aplicacion.
> > > > > > >
> > > > > > > El tema es que ahora necesitamos calcular datos como un promedio ponderado
> > > > > > > en el tiempo. Por ej (olvidandonos del campo alarma):
> > > > > > >
> > > > > > > codTag Valor FechaHora
> > > > > > > 1, 400, '1/1/1 00:00:00'
> > > > > > > 1, 200, '1/1/1 00:10:00'
> > > > > > > 1, 150, '1/1/1 00:30:00'
> > > > > > > 1, 100, '1/1/1 01:10:00'
> > > > > > >
> > > > > > > el promedio ponderado en el tiempo para el codTag = 1 es:
> > > > > > > 400 * 10 minutos (son 10 minutos porque ese es el tiempo que duro en ese
> > > > > > > valor)
> > > > > > > +
> > > > > > > 200 * 20
> > > > > > > +
> > > > > > > 150*40
> > > > > > > 000
> > > > > > > Todo dividido 70 minutos
> > > > > > > 0 (este es el promedio ponderado en el tiempo para este codTag en ese
> > > > > > > periodo)
> > > > > > > La pregunta es:
> > > > > > > ¿Se puede obtener este resultado sin recurrir a un cursor como actualmente
> > > > > > > se hace?
> > > > > > >
> > > > > > > ¿Es necesario proponer otra estructura en la tabla para mejorar el
> > > > > > > rendimiento y evitar el cursor?
> > > > > > >
> > > > > > > Hemos intentado hacer algo diferente precalculando valores mediante
> > > > > > > triggers, pero se complica porque los datos pueden llegar a entrar
> > > > > > > desordenados cronologicamente. Ejemplo, hoy pueden estar entrendo datos
> > > > > > > actuales y datos de ayer para el mismo codTag.
> > > > > > >
> > > > > > > Cualquier otra informacion que necesiten no duden en solicitarla.
> > > > > > >
> > > > > > > Muchas gracias por su tiempo.
> > > > > > >
> > > > > > > Saludos
> > > > > > >
> > > > > > > Horacio
> > > > > > >
> > > > > > >
email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida