Sugerencias para mejorar la SELECT de esta consulta.

07/09/2006 - 21:08 por Salvador Ramos | Informe spam
Hola a todos,

Estoy revisando con profiler una serie de ejecuciones y he visto esta
consulta que se ejecuta con bastante frecuencia, quería consultaros si se os
ocurre alguna forma de optimizarla (a parte de poner índices y demás que eso
ya lo tengo), es decir, obtener otra instrucción select que ofrezca los
mismos resultados y tenga mejor rendimiento.

Primero os explico la estructura de datos, intervienen tres tablas:
Clientes: Cliente, nombre, ... (Cliente es PK de Clientes)
Tarjetas: Cliente, Tarjeta, ... (Cliente es FK - relación uno a muchos con
Clientes, Tarjeta es PK de Tarjetas)
Servicios: Id, Tarjeta, Importe, ... (Id es PK de Servicios, Tarjeta es
FK -relación uno a muchos con Tarjetas)

select sum(importe) as sumaP
from servicios where fecha >= '20060709'
and tarjeta in (select tarjeta
from tarjetas
where cliente = (select cliente
from tarjetas
where tarjeta = 'ABCD' ))

Necesito que la consulta me devuelva la suma de los importes de todas las
tarjetas del cliente, por eso la select de nivel inferior obtiene el cliente
al que pertenece esa tarjeta, la del siguiente nivel obtiene la relación de
tarjetas de ese cliente, y ya la de nivel superior suma los importes de
todas esas tarjetas.

He intentado mejorarla, pero no lo he conseguido, y es una consulta que se
ejecuta con bastante frecuencia. Igual aún no he conectado 100% tras la
vuelta de vacaciones :-)

Muchas gracias

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)

Preguntas similare

Leer las respuestas

#6 Alejandro Mesa
08/09/2006 - 14:01 | Informe spam
Salvador,

Quizas puedas pedir que envien la consulta usando sp_executesql con
parametros, eso estaria muy cerca de usar un sp. En cuanto a lo demas, que
puedo decir, muchas compañias creen que por tener un buen programador vb.net,
c#, c++, etc, ya pueden crear una aplicacion que use SQL Server como backend,
sin prestar importancia, o quizas sin saber, que cuando se cargue informacion
en la db, es cuando se sabra si la db fue diseñada correctamente. Al
principio todo corre de maravilla, luego buscan a alguien para apagar el
fuego.

Suerte,

Alejandro Mesa

"Salvador Ramos" wrote:


Muchas gracias,

Me había obcecado en sacarlo con join entre las tres tablas, ha sido de esas
veces que no ves algo claro y que por más que pruebas te acabas liando. La
solución era un término medio una join y una subselect :-)

Comparto con vosotros que con las joins se obtiene mejor rendimiento.

La consulta se ejecuta desde la aplicación cliente, y ante eso no puedo
hacer nada, ya que la aplicación no es mía, y no puedo pedir ese tipo de
modificaciones a mi proveedor, me tendré que conformar con que me cambie la
instrución SELECT (pero nada de que utilice procedmientos almacenados, es
una pena), y esto lo hará porque había un fallo de cálculos en ella que he
detectado, y luego seguí la ejecución con profiler (la condición where la
hacía por fecha > y tenía que ser >=).

En cuanto al resto de temas sobre índices apropiados, clustered, non
clustered etc. Tengo que hacer una revisión de la base de datos, ya que creo
que la han creado con el Enterprise Manager sin preocuparse de nada, hay un
índice clustered por cada PK, además lo poco que visto que han hecho
adicional, tiene muy mala pinta. En la tabla clientes, además de hacer un
índice clustered por la PK (columna cliente), tiene otro indice non
clustered por esa misma columna. En la tabla servicios tiene un índice
clustered por Id (que es la PK), y además un índice non-clustered por Id,
Tarjeta, Fecha, lo cual no tiene ningún sentido.
En fin, que me toca pegar un repaso a fondo a todo esto.

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Alejandro Mesa" escribió en el
mensaje news:
> Salvador,
>
> Me pregunto cual columna estas usando en la tabla [servicios] para el
> indice
> clustered?. Si esta consulta, con digistes ante, es usada con frecuencia,
> entnnces usar la columna [fecha] para el indice clustered ayudaria
> muchisimo,
> ya que estas usando una comparacion abierta contra esta columna.
>
> ...
> where s.fecha >= '20060709'
> ...
>
> En la descripcion de las tablas, aparece la columna [Id] como clave
> primaria, pero no especificas si estas usando [clustered] para la clave
> primaria por defecto.
>
>
> AMB
>
> "Alejandro Mesa" wrote:
>
>> Salvador,
>>
>> Bienvenido de vuelta al grupo. Veo que aun no te recuperas de esas
>> vacaciones.
>>
>> Mi pregunta es como se ejecuta esa consulta, osea, desde un sp, o envias
>> la
>> consulta desde la aplicacion cliente, etc. Te lo pregunto por que quiero
>> saber si usas un parametro para pasar el valor de la tarjeta. Me parece,
>> como
>> sugirio Fredy, que el uso de joins vendria bien, aunque como bien sabes,
>> debes compara los planes de ejecucion y estadisticas de tiempo de ambas
>> sugerencias. Que tal si usamos:
>>
>> select
>> sum(importe) as sumaP
>> from
>> dbo.servicios as s
>> inner join
>> dbo.tarjetas as t
>> on s.tarjeta = t.tarjeta
>> where
>> s.fecha >= '20060709'
>> and t.cliente = (
>> select t1.cliente
>> from dbo.tarjetas as t1
>> where t1.tarjeta = @tarjeta
>> )
>> go
>>
>> Espero estes usando el dueño de la tabla cuando las referencias en la
>> consulta, recuerda que eso es muy importante para que el plan de
>> ejecucion
>> compilado pueda ser compartido por multiples usuarios. Tambien recalco
>> que el
>> valor de la tarjeta se pase como parametro, de esa forma el plan de
>> ejecucion
>> puede ser reusado, ya que el valor hash con el que este se identifica, es
>> calculado en base al texto de la consulta, por lo que la misma consulta
>> con
>> diferentes valores de tarjeta resultarian en diferentes planes de
>> ejecucion.
>> Como ultimo, no uses una variable intermedia para traer el valor de la
>> columna [cliente] y luego usar esta variable en la consulta, pues
>> entonces
>> SQL Server, al no saber el valor de la variable en tiempo de compilacion,
>> usara la densidad del indice, en vez de las estadisticas, para estimar
>> las
>> filas que machan la condicion de busqueda.
>>
>>
>> Saludos,
>>
>> Alejandro Mesa
>>
>> "Salvador Ramos" wrote:
>>
>> > Hola a todos,
>> >
>> > Estoy revisando con profiler una serie de ejecuciones y he visto esta
>> > consulta que se ejecuta con bastante frecuencia, quería consultaros si
>> > se os
>> > ocurre alguna forma de optimizarla (a parte de poner índices y demás
>> > que eso
>> > ya lo tengo), es decir, obtener otra instrucción select que ofrezca los
>> > mismos resultados y tenga mejor rendimiento.
>> >
>> > Primero os explico la estructura de datos, intervienen tres tablas:
>> > Clientes: Cliente, nombre, ... (Cliente es PK de Clientes)
>> > Tarjetas: Cliente, Tarjeta, ... (Cliente es FK - relación uno a muchos
>> > con
>> > Clientes, Tarjeta es PK de Tarjetas)
>> > Servicios: Id, Tarjeta, Importe, ... (Id es PK de Servicios, Tarjeta es
>> > FK -relación uno a muchos con Tarjetas)
>> >
>> > select sum(importe) as sumaP
>> > from servicios where fecha >= '20060709'
>> > and tarjeta in (select tarjeta
>> > from tarjetas
>> > where cliente = (select cliente
>> > from tarjetas
>> > where tarjeta = 'ABCD' ))
>> >
>> > Necesito que la consulta me devuelva la suma de los importes de todas
>> > las
>> > tarjetas del cliente, por eso la select de nivel inferior obtiene el
>> > cliente
>> > al que pertenece esa tarjeta, la del siguiente nivel obtiene la
>> > relación de
>> > tarjetas de ese cliente, y ya la de nivel superior suma los importes de
>> > todas esas tarjetas.
>> >
>> > He intentado mejorarla, pero no lo he conseguido, y es una consulta que
>> > se
>> > ejecuta con bastante frecuencia. Igual aún no he conectado 100% tras la
>> > vuelta de vacaciones :-)
>> >
>> > Muchas gracias
>> >
>> > Un saludo
>> > Salvador Ramos
>> > Murcia - España
>> >
>> > [Microsoft MVP SQL Server]
>> > www.helpdna.net (información sobre SQL Server y .NET)
>> >
>> >
>> >
>> >



Respuesta Responder a este mensaje
#7 Salvador Ramos
08/09/2006 - 14:19 | Informe spam
Totalmente de acuerdo.

Por eso estoy haciendo una revisión más exhaustiva de lo que están enviando
al servidor y del DDL, porque estoy harto de encontrarme con estas
situaciones.
Además le he preguntado que tal iba el rendimiento con ciertos volúmenes de
datos, y me dicen que sólo han probado con muy pocas filas :-S (bueno, pero
ya me encargo yo de afinarlo y currar por ellos esa parte, lo importante es
que funcione bien el sistema en mi empresa).

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Alejandro Mesa" escribió en el
mensaje news:
Salvador,

Quizas puedas pedir que envien la consulta usando sp_executesql con
parametros, eso estaria muy cerca de usar un sp. En cuanto a lo demas, que
puedo decir, muchas compañias creen que por tener un buen programador
vb.net,
c#, c++, etc, ya pueden crear una aplicacion que use SQL Server como
backend,
sin prestar importancia, o quizas sin saber, que cuando se cargue
informacion
en la db, es cuando se sabra si la db fue diseñada correctamente. Al
principio todo corre de maravilla, luego buscan a alguien para apagar el
fuego.

Suerte,

Alejandro Mesa

"Salvador Ramos" wrote:


Muchas gracias,

Me había obcecado en sacarlo con join entre las tres tablas, ha sido de
esas
veces que no ves algo claro y que por más que pruebas te acabas liando.
La
solución era un término medio una join y una subselect :-)

Comparto con vosotros que con las joins se obtiene mejor rendimiento.

La consulta se ejecuta desde la aplicación cliente, y ante eso no puedo
hacer nada, ya que la aplicación no es mía, y no puedo pedir ese tipo de
modificaciones a mi proveedor, me tendré que conformar con que me cambie
la
instrución SELECT (pero nada de que utilice procedmientos almacenados, es
una pena), y esto lo hará porque había un fallo de cálculos en ella que
he
detectado, y luego seguí la ejecución con profiler (la condición where
la
hacía por fecha > y tenía que ser >=).

En cuanto al resto de temas sobre índices apropiados, clustered, non
clustered etc. Tengo que hacer una revisión de la base de datos, ya que
creo
que la han creado con el Enterprise Manager sin preocuparse de nada, hay
un
índice clustered por cada PK, además lo poco que visto que han hecho
adicional, tiene muy mala pinta. En la tabla clientes, además de hacer un
índice clustered por la PK (columna cliente), tiene otro indice non
clustered por esa misma columna. En la tabla servicios tiene un índice
clustered por Id (que es la PK), y además un índice non-clustered por Id,
Tarjeta, Fecha, lo cual no tiene ningún sentido.
En fin, que me toca pegar un repaso a fondo a todo esto.

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Alejandro Mesa" escribió en el
mensaje news:
> Salvador,
>
> Me pregunto cual columna estas usando en la tabla [servicios] para el
> indice
> clustered?. Si esta consulta, con digistes ante, es usada con
> frecuencia,
> entnnces usar la columna [fecha] para el indice clustered ayudaria
> muchisimo,
> ya que estas usando una comparacion abierta contra esta columna.
>
> ...
> where s.fecha >= '20060709'
> ...
>
> En la descripcion de las tablas, aparece la columna [Id] como clave
> primaria, pero no especificas si estas usando [clustered] para la clave
> primaria por defecto.
>
>
> AMB
>
> "Alejandro Mesa" wrote:
>
>> Salvador,
>>
>> Bienvenido de vuelta al grupo. Veo que aun no te recuperas de esas
>> vacaciones.
>>
>> Mi pregunta es como se ejecuta esa consulta, osea, desde un sp, o
>> envias
>> la
>> consulta desde la aplicacion cliente, etc. Te lo pregunto por que
>> quiero
>> saber si usas un parametro para pasar el valor de la tarjeta. Me
>> parece,
>> como
>> sugirio Fredy, que el uso de joins vendria bien, aunque como bien
>> sabes,
>> debes compara los planes de ejecucion y estadisticas de tiempo de
>> ambas
>> sugerencias. Que tal si usamos:
>>
>> select
>> sum(importe) as sumaP
>> from
>> dbo.servicios as s
>> inner join
>> dbo.tarjetas as t
>> on s.tarjeta = t.tarjeta
>> where
>> s.fecha >= '20060709'
>> and t.cliente = (
>> select t1.cliente
>> from dbo.tarjetas as t1
>> where t1.tarjeta = @tarjeta
>> )
>> go
>>
>> Espero estes usando el dueño de la tabla cuando las referencias en la
>> consulta, recuerda que eso es muy importante para que el plan de
>> ejecucion
>> compilado pueda ser compartido por multiples usuarios. Tambien recalco
>> que el
>> valor de la tarjeta se pase como parametro, de esa forma el plan de
>> ejecucion
>> puede ser reusado, ya que el valor hash con el que este se identifica,
>> es
>> calculado en base al texto de la consulta, por lo que la misma
>> consulta
>> con
>> diferentes valores de tarjeta resultarian en diferentes planes de
>> ejecucion.
>> Como ultimo, no uses una variable intermedia para traer el valor de la
>> columna [cliente] y luego usar esta variable en la consulta, pues
>> entonces
>> SQL Server, al no saber el valor de la variable en tiempo de
>> compilacion,
>> usara la densidad del indice, en vez de las estadisticas, para estimar
>> las
>> filas que machan la condicion de busqueda.
>>
>>
>> Saludos,
>>
>> Alejandro Mesa
>>
>> "Salvador Ramos" wrote:
>>
>> > Hola a todos,
>> >
>> > Estoy revisando con profiler una serie de ejecuciones y he visto
>> > esta
>> > consulta que se ejecuta con bastante frecuencia, quería consultaros
>> > si
>> > se os
>> > ocurre alguna forma de optimizarla (a parte de poner índices y demás
>> > que eso
>> > ya lo tengo), es decir, obtener otra instrucción select que ofrezca
>> > los
>> > mismos resultados y tenga mejor rendimiento.
>> >
>> > Primero os explico la estructura de datos, intervienen tres tablas:
>> > Clientes: Cliente, nombre, ... (Cliente es PK de Clientes)
>> > Tarjetas: Cliente, Tarjeta, ... (Cliente es FK - relación uno a
>> > muchos
>> > con
>> > Clientes, Tarjeta es PK de Tarjetas)
>> > Servicios: Id, Tarjeta, Importe, ... (Id es PK de Servicios, Tarjeta
>> > es
>> > FK -relación uno a muchos con Tarjetas)
>> >
>> > select sum(importe) as sumaP
>> > from servicios where fecha >= '20060709'
>> > and tarjeta in (select tarjeta
>> > from tarjetas
>> > where cliente = (select cliente
>> > from tarjetas
>> > where tarjeta = 'ABCD' ))
>> >
>> > Necesito que la consulta me devuelva la suma de los importes de
>> > todas
>> > las
>> > tarjetas del cliente, por eso la select de nivel inferior obtiene el
>> > cliente
>> > al que pertenece esa tarjeta, la del siguiente nivel obtiene la
>> > relación de
>> > tarjetas de ese cliente, y ya la de nivel superior suma los importes
>> > de
>> > todas esas tarjetas.
>> >
>> > He intentado mejorarla, pero no lo he conseguido, y es una consulta
>> > que
>> > se
>> > ejecuta con bastante frecuencia. Igual aún no he conectado 100% tras
>> > la
>> > vuelta de vacaciones :-)
>> >
>> > Muchas gracias
>> >
>> > Un saludo
>> > Salvador Ramos
>> > Murcia - España
>> >
>> > [Microsoft MVP SQL Server]
>> > www.helpdna.net (información sobre SQL Server y .NET)
>> >
>> >
>> >
>> >



Respuesta Responder a este mensaje
#8 Manuel Etcheto
09/09/2006 - 00:32 | Informe spam
Hola Salvador
si se supone que las operaciones no cambian hacia atrás en el tiempo, ¿no
podés cada noche grabar dia-cliente-suma en otra tabla?
Ahí estaría la gran diferencia.

Salu2
Manuel


"Salvador Ramos" escribió en el
mensaje news:
Totalmente de acuerdo.

Por eso estoy haciendo una revisión más exhaustiva de lo que están
enviando al servidor y del DDL, porque estoy harto de encontrarme con
estas situaciones.
Además le he preguntado que tal iba el rendimiento con ciertos volúmenes
de datos, y me dicen que sólo han probado con muy pocas filas :-S (bueno,
pero ya me encargo yo de afinarlo y currar por ellos esa parte, lo
importante es que funcione bien el sistema en mi empresa).

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Alejandro Mesa" escribió en el
mensaje news:
Salvador,

Quizas puedas pedir que envien la consulta usando sp_executesql con
parametros, eso estaria muy cerca de usar un sp. En cuanto a lo demas,
que
puedo decir, muchas compañias creen que por tener un buen programador
vb.net,
c#, c++, etc, ya pueden crear una aplicacion que use SQL Server como
backend,
sin prestar importancia, o quizas sin saber, que cuando se cargue
informacion
en la db, es cuando se sabra si la db fue diseñada correctamente. Al
principio todo corre de maravilla, luego buscan a alguien para apagar el
fuego.

Suerte,

Alejandro Mesa

"Salvador Ramos" wrote:


Muchas gracias,

Me había obcecado en sacarlo con join entre las tres tablas, ha sido de
esas
veces que no ves algo claro y que por más que pruebas te acabas liando.
La
solución era un término medio una join y una subselect :-)

Comparto con vosotros que con las joins se obtiene mejor rendimiento.

La consulta se ejecuta desde la aplicación cliente, y ante eso no puedo
hacer nada, ya que la aplicación no es mía, y no puedo pedir ese tipo de
modificaciones a mi proveedor, me tendré que conformar con que me cambie
la
instrución SELECT (pero nada de que utilice procedmientos almacenados,
es
una pena), y esto lo hará porque había un fallo de cálculos en ella que
he
detectado, y luego seguí la ejecución con profiler (la condición where
la
hacía por fecha > y tenía que ser >=).

En cuanto al resto de temas sobre índices apropiados, clustered, non
clustered etc. Tengo que hacer una revisión de la base de datos, ya que
creo
que la han creado con el Enterprise Manager sin preocuparse de nada, hay
un
índice clustered por cada PK, además lo poco que visto que han hecho
adicional, tiene muy mala pinta. En la tabla clientes, además de hacer
un
índice clustered por la PK (columna cliente), tiene otro indice non
clustered por esa misma columna. En la tabla servicios tiene un índice
clustered por Id (que es la PK), y además un índice non-clustered por
Id,
Tarjeta, Fecha, lo cual no tiene ningún sentido.
En fin, que me toca pegar un repaso a fondo a todo esto.

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Alejandro Mesa" escribió en
el
mensaje news:
> Salvador,
>
> Me pregunto cual columna estas usando en la tabla [servicios] para el
> indice
> clustered?. Si esta consulta, con digistes ante, es usada con
> frecuencia,
> entnnces usar la columna [fecha] para el indice clustered ayudaria
> muchisimo,
> ya que estas usando una comparacion abierta contra esta columna.
>
> ...
> where s.fecha >= '20060709'
> ...
>
> En la descripcion de las tablas, aparece la columna [Id] como clave
> primaria, pero no especificas si estas usando [clustered] para la
> clave
> primaria por defecto.
>
>
> AMB
>
> "Alejandro Mesa" wrote:
>
>> Salvador,
>>
>> Bienvenido de vuelta al grupo. Veo que aun no te recuperas de esas
>> vacaciones.
>>
>> Mi pregunta es como se ejecuta esa consulta, osea, desde un sp, o
>> envias
>> la
>> consulta desde la aplicacion cliente, etc. Te lo pregunto por que
>> quiero
>> saber si usas un parametro para pasar el valor de la tarjeta. Me
>> parece,
>> como
>> sugirio Fredy, que el uso de joins vendria bien, aunque como bien
>> sabes,
>> debes compara los planes de ejecucion y estadisticas de tiempo de
>> ambas
>> sugerencias. Que tal si usamos:
>>
>> select
>> sum(importe) as sumaP
>> from
>> dbo.servicios as s
>> inner join
>> dbo.tarjetas as t
>> on s.tarjeta = t.tarjeta
>> where
>> s.fecha >= '20060709'
>> and t.cliente = (
>> select t1.cliente
>> from dbo.tarjetas as t1
>> where t1.tarjeta = @tarjeta
>> )
>> go
>>
>> Espero estes usando el dueño de la tabla cuando las referencias en la
>> consulta, recuerda que eso es muy importante para que el plan de
>> ejecucion
>> compilado pueda ser compartido por multiples usuarios. Tambien
>> recalco
>> que el
>> valor de la tarjeta se pase como parametro, de esa forma el plan de
>> ejecucion
>> puede ser reusado, ya que el valor hash con el que este se
>> identifica, es
>> calculado en base al texto de la consulta, por lo que la misma
>> consulta
>> con
>> diferentes valores de tarjeta resultarian en diferentes planes de
>> ejecucion.
>> Como ultimo, no uses una variable intermedia para traer el valor de
>> la
>> columna [cliente] y luego usar esta variable en la consulta, pues
>> entonces
>> SQL Server, al no saber el valor de la variable en tiempo de
>> compilacion,
>> usara la densidad del indice, en vez de las estadisticas, para
>> estimar
>> las
>> filas que machan la condicion de busqueda.
>>
>>
>> Saludos,
>>
>> Alejandro Mesa
>>
>> "Salvador Ramos" wrote:
>>
>> > Hola a todos,
>> >
>> > Estoy revisando con profiler una serie de ejecuciones y he visto
>> > esta
>> > consulta que se ejecuta con bastante frecuencia, quería consultaros
>> > si
>> > se os
>> > ocurre alguna forma de optimizarla (a parte de poner índices y
>> > demás
>> > que eso
>> > ya lo tengo), es decir, obtener otra instrucción select que ofrezca
>> > los
>> > mismos resultados y tenga mejor rendimiento.
>> >
>> > Primero os explico la estructura de datos, intervienen tres tablas:
>> > Clientes: Cliente, nombre, ... (Cliente es PK de Clientes)
>> > Tarjetas: Cliente, Tarjeta, ... (Cliente es FK - relación uno a
>> > muchos
>> > con
>> > Clientes, Tarjeta es PK de Tarjetas)
>> > Servicios: Id, Tarjeta, Importe, ... (Id es PK de Servicios,
>> > Tarjeta es
>> > FK -relación uno a muchos con Tarjetas)
>> >
>> > select sum(importe) as sumaP
>> > from servicios where fecha >= '20060709'
>> > and tarjeta in (select tarjeta
>> > from tarjetas
>> > where cliente = (select cliente
>> > from tarjetas
>> > where tarjeta = 'ABCD' ))
>> >
>> > Necesito que la consulta me devuelva la suma de los importes de
>> > todas
>> > las
>> > tarjetas del cliente, por eso la select de nivel inferior obtiene
>> > el
>> > cliente
>> > al que pertenece esa tarjeta, la del siguiente nivel obtiene la
>> > relación de
>> > tarjetas de ese cliente, y ya la de nivel superior suma los
>> > importes de
>> > todas esas tarjetas.
>> >
>> > He intentado mejorarla, pero no lo he conseguido, y es una consulta
>> > que
>> > se
>> > ejecuta con bastante frecuencia. Igual aún no he conectado 100%
>> > tras la
>> > vuelta de vacaciones :-)
>> >
>> > Muchas gracias
>> >
>> > Un saludo
>> > Salvador Ramos
>> > Murcia - España
>> >
>> > [Microsoft MVP SQL Server]
>> > www.helpdna.net (información sobre SQL Server y .NET)
>> >
>> >
>> >
>> >









Respuesta Responder a este mensaje
#9 Salvador Ramos
09/09/2006 - 18:59 | Informe spam
Hola,

Conozco la opción de tener esos datos denormalizados, pero se puede obtener
un buen rendimiento también sin ello, y es lo que pretendo. En este caso por
el volumen de operaciones que se deben sumar, según los datos reales de debo
tener es pequeño, por lo que, para mi caso veo mejor opcón no almacenar esos
datos denormalizados en una tabla.

Además no tengo opción, la aplicación no es mía, simplemente estoy viendo
las instrucciones que ejecuta por Profiler.

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Manuel Etcheto" escribió en el mensaje
news:
Hola Salvador
si se supone que las operaciones no cambian hacia atrás en el tiempo, ¿no
podés cada noche grabar dia-cliente-suma en otra tabla?
Ahí estaría la gran diferencia.

Salu2
Manuel


"Salvador Ramos" escribió en el
mensaje news:
Totalmente de acuerdo.

Por eso estoy haciendo una revisión más exhaustiva de lo que están
enviando al servidor y del DDL, porque estoy harto de encontrarme con
estas situaciones.
Además le he preguntado que tal iba el rendimiento con ciertos volúmenes
de datos, y me dicen que sólo han probado con muy pocas filas :-S (bueno,
pero ya me encargo yo de afinarlo y currar por ellos esa parte, lo
importante es que funcione bien el sistema en mi empresa).

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Alejandro Mesa" escribió en el
mensaje news:
Salvador,

Quizas puedas pedir que envien la consulta usando sp_executesql con
parametros, eso estaria muy cerca de usar un sp. En cuanto a lo demas,
que
puedo decir, muchas compañias creen que por tener un buen programador
vb.net,
c#, c++, etc, ya pueden crear una aplicacion que use SQL Server como
backend,
sin prestar importancia, o quizas sin saber, que cuando se cargue
informacion
en la db, es cuando se sabra si la db fue diseñada correctamente. Al
principio todo corre de maravilla, luego buscan a alguien para apagar el
fuego.

Suerte,

Alejandro Mesa

"Salvador Ramos" wrote:


Muchas gracias,

Me había obcecado en sacarlo con join entre las tres tablas, ha sido de
esas
veces que no ves algo claro y que por más que pruebas te acabas liando.
La
solución era un término medio una join y una subselect :-)

Comparto con vosotros que con las joins se obtiene mejor rendimiento.

La consulta se ejecuta desde la aplicación cliente, y ante eso no puedo
hacer nada, ya que la aplicación no es mía, y no puedo pedir ese tipo
de
modificaciones a mi proveedor, me tendré que conformar con que me
cambie la
instrución SELECT (pero nada de que utilice procedmientos almacenados,
es
una pena), y esto lo hará porque había un fallo de cálculos en ella que
he
detectado, y luego seguí la ejecución con profiler (la condición where
la
hacía por fecha > y tenía que ser >=).

En cuanto al resto de temas sobre índices apropiados, clustered, non
clustered etc. Tengo que hacer una revisión de la base de datos, ya que
creo
que la han creado con el Enterprise Manager sin preocuparse de nada,
hay un
índice clustered por cada PK, además lo poco que visto que han hecho
adicional, tiene muy mala pinta. En la tabla clientes, además de hacer
un
índice clustered por la PK (columna cliente), tiene otro indice non
clustered por esa misma columna. En la tabla servicios tiene un índice
clustered por Id (que es la PK), y además un índice non-clustered por
Id,
Tarjeta, Fecha, lo cual no tiene ningún sentido.
En fin, que me toca pegar un repaso a fondo a todo esto.

Un saludo
Salvador Ramos
Murcia - España

[Microsoft MVP SQL Server]
www.helpdna.net (información sobre SQL Server y .NET)


"Alejandro Mesa" escribió en
el
mensaje news:
> Salvador,
>
> Me pregunto cual columna estas usando en la tabla [servicios] para el
> indice
> clustered?. Si esta consulta, con digistes ante, es usada con
> frecuencia,
> entnnces usar la columna [fecha] para el indice clustered ayudaria
> muchisimo,
> ya que estas usando una comparacion abierta contra esta columna.
>
> ...
> where s.fecha >= '20060709'
> ...
>
> En la descripcion de las tablas, aparece la columna [Id] como clave
> primaria, pero no especificas si estas usando [clustered] para la
> clave
> primaria por defecto.
>
>
> AMB
>
> "Alejandro Mesa" wrote:
>
>> Salvador,
>>
>> Bienvenido de vuelta al grupo. Veo que aun no te recuperas de esas
>> vacaciones.
>>
>> Mi pregunta es como se ejecuta esa consulta, osea, desde un sp, o
>> envias
>> la
>> consulta desde la aplicacion cliente, etc. Te lo pregunto por que
>> quiero
>> saber si usas un parametro para pasar el valor de la tarjeta. Me
>> parece,
>> como
>> sugirio Fredy, que el uso de joins vendria bien, aunque como bien
>> sabes,
>> debes compara los planes de ejecucion y estadisticas de tiempo de
>> ambas
>> sugerencias. Que tal si usamos:
>>
>> select
>> sum(importe) as sumaP
>> from
>> dbo.servicios as s
>> inner join
>> dbo.tarjetas as t
>> on s.tarjeta = t.tarjeta
>> where
>> s.fecha >= '20060709'
>> and t.cliente = (
>> select t1.cliente
>> from dbo.tarjetas as t1
>> where t1.tarjeta = @tarjeta
>> )
>> go
>>
>> Espero estes usando el dueño de la tabla cuando las referencias en
>> la
>> consulta, recuerda que eso es muy importante para que el plan de
>> ejecucion
>> compilado pueda ser compartido por multiples usuarios. Tambien
>> recalco
>> que el
>> valor de la tarjeta se pase como parametro, de esa forma el plan de
>> ejecucion
>> puede ser reusado, ya que el valor hash con el que este se
>> identifica, es
>> calculado en base al texto de la consulta, por lo que la misma
>> consulta
>> con
>> diferentes valores de tarjeta resultarian en diferentes planes de
>> ejecucion.
>> Como ultimo, no uses una variable intermedia para traer el valor de
>> la
>> columna [cliente] y luego usar esta variable en la consulta, pues
>> entonces
>> SQL Server, al no saber el valor de la variable en tiempo de
>> compilacion,
>> usara la densidad del indice, en vez de las estadisticas, para
>> estimar
>> las
>> filas que machan la condicion de busqueda.
>>
>>
>> Saludos,
>>
>> Alejandro Mesa
>>
>> "Salvador Ramos" wrote:
>>
>> > Hola a todos,
>> >
>> > Estoy revisando con profiler una serie de ejecuciones y he visto
>> > esta
>> > consulta que se ejecuta con bastante frecuencia, quería
>> > consultaros si
>> > se os
>> > ocurre alguna forma de optimizarla (a parte de poner índices y
>> > demás
>> > que eso
>> > ya lo tengo), es decir, obtener otra instrucción select que
>> > ofrezca los
>> > mismos resultados y tenga mejor rendimiento.
>> >
>> > Primero os explico la estructura de datos, intervienen tres
>> > tablas:
>> > Clientes: Cliente, nombre, ... (Cliente es PK de Clientes)
>> > Tarjetas: Cliente, Tarjeta, ... (Cliente es FK - relación uno a
>> > muchos
>> > con
>> > Clientes, Tarjeta es PK de Tarjetas)
>> > Servicios: Id, Tarjeta, Importe, ... (Id es PK de Servicios,
>> > Tarjeta es
>> > FK -relación uno a muchos con Tarjetas)
>> >
>> > select sum(importe) as sumaP
>> > from servicios where fecha >= '20060709'
>> > and tarjeta in (select tarjeta
>> > from tarjetas
>> > where cliente = (select cliente
>> > from tarjetas
>> > where tarjeta = 'ABCD' ))
>> >
>> > Necesito que la consulta me devuelva la suma de los importes de
>> > todas
>> > las
>> > tarjetas del cliente, por eso la select de nivel inferior obtiene
>> > el
>> > cliente
>> > al que pertenece esa tarjeta, la del siguiente nivel obtiene la
>> > relación de
>> > tarjetas de ese cliente, y ya la de nivel superior suma los
>> > importes de
>> > todas esas tarjetas.
>> >
>> > He intentado mejorarla, pero no lo he conseguido, y es una
>> > consulta que
>> > se
>> > ejecuta con bastante frecuencia. Igual aún no he conectado 100%
>> > tras la
>> > vuelta de vacaciones :-)
>> >
>> > Muchas gracias
>> >
>> > Un saludo
>> > Salvador Ramos
>> > Murcia - España
>> >
>> > [Microsoft MVP SQL Server]
>> > www.helpdna.net (información sobre SQL Server y .NET)
>> >
>> >
>> >
>> >













email Siga el debate Respuesta Responder a este mensaje
Ads by Google
Help Hacer una pregunta AnteriorRespuesta Tengo una respuesta
Search Busqueda sugerida