entre Desarrolladores

Recibe ayuda de expertos

Registrate y pregunta

Es gratis y fácil

Recibe respuestas

Respuestas, votos y comentarios

Vota y selecciona respuestas

Recibe puntos, vota y da la solución

Pregunta

2votos

Diferencias de rendimiento entre consultas de una misma vista

En este caso voy a utilizar únicamente 4 tablast_cita, t_estados_cita, t_punto_venta y t_viajero .

  • t_cita almacena las citas concertadas para una cierta fecha
  • t_estados_cita almacena el estado en que se encuentra la cita: Creada, Bloqueada, Concertada, Anulada...
  • t_punto_venta almacena el establecimiento que va a atender la cita
  • t_viajero almacena el usuario que ha concertado la cita

He generado la siguiente vista para consultar las citas concertadas y bloqueadas en el último mes:

 `CREATE VIEW [dbo].[v_cita_estado_oficina]
AS
SELECT     c.Id, p.Id AS Id_oficina, p.Denominacion, ec.Estado, c.Fecha, ec.razon, ec.Incidencias, NULL AS Documento, NULL AS Telefono, NULL AS Correo
FROM         t_cita c, t_estados_cita ec, t_punto_venta p
WHERE     c.Fecha > DATEADD(month, - 1, GETDATE()) AND c.Id = ec.Id_cita AND ec.Estado = 'Bloqueada' AND p.Id = c.Id_punto_venta AND ec.Id IN
                          (SELECT     MAX(b.Id)
                            FROM          t_cita a, t_estados_cita b
                            WHERE      a.Id = b.Id_cita AND a.Fecha >= DATEADD(month, - 1, GETDATE())
                            GROUP BY a.Fecha, a.Id_punto_venta)
UNION
(SELECT     c.Id, p.Id AS Id_oficina, p.Denominacion, ec.Estado, c.Fecha, ec.Razon, ec.Incidencias, v.Documento_personal, v.Telefono1, v.Correo_electronico
 FROM         t_cita c, t_estados_cita ec, t_punto_venta p, t_viajero v
 WHERE     c.Fecha > DATEADD(month, - 1, GETDATE()) AND c.Id = ec.Id_cita AND p.Id = c.Id_punto_venta AND c.Id_viajero IS NOT NULL AND c.Id_viajero = v.Id AND 
                        c.Id NOT IN
                            (SELECT     c.Id
                              FROM          t_cita c, t_estados_cita ec
                              WHERE      c.Id = ec.Id_cita AND c.Id_viajero IS NOT NULL AND c.Fecha >= DATEADD(month, - 1, GETDATE()) 
                              AND (ec.Estado = 'Cancelada')) AND ec.Id IN
                            (SELECT     MAX(b.Id)
                              FROM          t_cita a, t_estados_cita b
                              WHERE      a.Id = b.Id_cita AND a.Fecha >= DATEADD(month, - 1, GETDATE())
                              GROUP BY a.Fecha, a.Id_punto_venta))
`

El caso es que al realizar una consulta para que me de las citas de un punto de venta de los antiguos, por ejemplo:

select * from v_cita_estado_oficina where Id_oficina = 11 and Estado = 'Concertada'

lo hace rapidísimo, no tarda apenas unos segundos. Pero cuando hago la misma consulta para un punto de venta nueva por ejemplo:

select * from v_cita_estado_oficina where Id_oficina = 32 and Estado = 'Concertada'

La consulta llega a tardar hasta 2minutos y 30 segundos, lo cual es inviable.

He analizado los Planes de ejecución para ambas consultas y son diferentes. En la segunda consulta hay un Sort que consume hasta el 70% del tiempo. Espero que alguien me pueda ayudar a optimizar esta consulta. Un saludo y gracias.

2 Respuestas

2votos

Leonardo-Tadei Puntos227320

Hola Javier,

por lo que describís, lo más probable es que no tengas indexada las tablas por los criterios de ordenamiento y relación.

Tal vez ejecutaste alguna optimización manual sobre los datos, con lo que la primera parte de las tablas está ordenada, y por tanto la búsqueda es más veloz, pero los datos nuevos quedan fuera de ese orden manual y el motor tiene primero que ejecutar el sort y después hacer la búsqueda.

Fijate que exista un índice por Id_oficina y otro por Estado. También fijate que existan índices por los campos que se usan con criterio de relación entre las tablas.

Saludos!

0voto

javiermadueno comentado

Hola Leonardo, lo primero gracias por tu respuesta.
La tabla t_citas tiene los siguientes indices:
-PK_t_cita (Clustered)
-IX_ID_OFICINA (Non-unique, Non-clustered)
-IX_FECHA_CITA(Non-unique, Non Clustered)

La tabla t_estados_cita tiene los siguientes:
-PK_t_estados_cita (Clustered)

  • IX_ID_CITA (Non-unique, Non Clustered)
  • IX_FECHA_CITA (Non-unique, Non Clustered)

He probado a reconstruirlos todos pero no cambia obsolutamente nada

Editado: movido a comentario de la respuesta

0voto

Leonardo-Tadei comentado

Hola Javier,

por lo que veo, estás haciendo JOINs con los campos id_punto_venta y id_viajero de la tabla t_cita, pero esos campos no son accesibles vía un índice.

Estoy asumiendo que el índice IX_FECHA_CITA se corresponde con el campo fecha que usás en la query y no con otro campo.

Sin tener la estructura completa de las tablas parte de esto es adivinanza, pero seguro que estos índices faltantes influyen.

Tampoco tenés el modelo relacional completamente normalizado, lo cual también disminuye la performance: los estados de citas por lo que filtrás deberían ser el ID de dicho estado y no su string representativo (tal vez sí puedas filtrar por ID de Estado sin cambios y solo sea un desliz en la escritura de la query).

Es una pena que el planificador no te diga sobre qué subconjunto de querys se ejecuta el sort... sería mucho más fácil saber en qué se gasta todo ese tiempo.

Saludos cordiales.
Contanos cómo et fue luego de crar los índices!

0voto

Jonathino25 Puntos1740

cambia el in por exists y el not in por not exists

Por favor, accede o regístrate para responder a esta pregunta.

Otras Preguntas y Respuestas


...

Bienvenido a entre Desarrolladores, donde puedes realizar preguntas y recibir respuestas de otros miembros de la comunidad.

Conecta