Cuando se utiliza una subconsulta para encontrar el recuento total de todos los registros anteriores con un campo coincidente, el rendimiento es terrible en una tabla con tan solo 50k registros. Sin la subconsulta, la consulta se ejecuta en unos pocos milisegundos. Con la subconsulta, el tiempo de ejecución es más de un minuto.
Para esta consulta, el resultado debe:
- Incluya solo aquellos registros dentro de un rango de fechas dado.
- Incluya un recuento de todos los registros anteriores, sin incluir el registro actual, independientemente del rango de fechas.
Esquema de tabla básico
Activity
======================
Id int Identifier
Address varchar(25)
ActionDate datetime2
Process varchar(50)
-- 7 other columns
Datos de ejemplo
Id Address ActionDate (Time part excluded for simplicity)
===========================
99 000 2017-05-30
98 111 2017-05-30
97 000 2017-05-29
96 000 2017-05-28
95 111 2017-05-19
94 222 2017-05-30
Resultados previstos
Para el rango de fechas de 2017-05-29
a2017-05-30
Id Address ActionDate PriorCount
=========================================
99 000 2017-05-30 2 (3 total, 2 prior to ActionDate)
98 111 2017-05-30 1 (2 total, 1 prior to ActionDate)
94 222 2017-05-30 0 (1 total, 0 prior to ActionDate)
97 000 2017-05-29 1 (3 total, 1 prior to ActionDate)
Los registros 96 y 95 se excluyen del resultado, pero se incluyen en la PriorCount
subconsulta
Consulta actual
select
*.a
, ( select count(*)
from Activity
where
Activity.Address = a.Address
and Activity.ActionDate < a.ActionDate
) as PriorCount
from Activity a
where a.ActionDate between '2017-05-29' and '2017-05-30'
order by a.ActionDate desc
Índice actual
CREATE NONCLUSTERED INDEX [IDX_my_nme] ON [dbo].[Activity]
(
[ActionDate] ASC
)
INCLUDE ([Address]) WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
)
Pregunta
- ¿Qué estrategias podrían usarse para mejorar el rendimiento de esta consulta?
Edición 1
En respuesta a la pregunta de qué puedo modificar en la base de datos: puedo modificar los índices, pero no la estructura de la tabla.
Edición 2
Ahora he agregado un índice básico en la Address
columna, pero eso no parece mejorar mucho. Actualmente estoy encontrando un rendimiento mucho mejor con la creación de una tabla temporal e insertando los valores sin el PriorCount
y luego actualizando cada fila con sus recuentos específicos.
Editar 3
El índice Spool Joe Obbish (respuesta aceptada) encontrado fue el problema. Una vez que agregué una nueva nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, los tiempos de consulta disminuyeron de más de un minuto a menos de un segundo sin usar una tabla temporal (ver edición 2).
nonclustered index [xyz] on [Activity] (Address) include (ActionDate)
, los tiempos de consulta disminuyeron de más de un minuto a menos de un segundo. +10 si pudiera. ¡Gracias!