Uso de Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64).
Dada una tabla e índice:
create table [User].[Session]
(
SessionId int identity(1, 1) not null primary key
CreatedUtc datetime2(7) not null default sysutcdatetime())
)
create nonclustered index [IX_User_Session_CreatedUtc]
on [User].[Session]([CreatedUtc]) include (SessionId)
Las filas reales para cada una de las siguientes consultas son 3.1M, las filas estimadas se muestran como comentarios.
Cuando estas consultas alimentan otra consulta en una Vista , el optimizador elige una unión en bucle debido a las estimaciones de 1 fila. ¿Cómo mejorar la estimación a este nivel del suelo para evitar anular la sugerencia de combinación de consulta principal o recurrir a un SP?
Usar una fecha codificada funciona muy bien:
select distinct SessionId from [User].Session -- 2.9M (great)
where CreatedUtc > '04/08/2015' -- but hardcoded
Estas consultas equivalentes son compatibles con la vista, pero todas estiman 1 fila:
select distinct SessionId from [User].Session -- 1
where CreatedUtc > dateadd(day, -365, sysutcdatetime())
select distinct SessionId from [User].Session -- 1
where dateadd(day, 365, CreatedUtc) > sysutcdatetime();
select distinct SessionId from [User].Session s -- 1
inner loop join (select dateadd(day, -365, sysutcdatetime()) as MinCreatedUtc) d
on d.MinCreatedUtc < s.CreatedUtc
-- (also tried reversing join order, not shown, no change)
select distinct SessionId from [User].Session s -- 1
cross apply (select dateadd(day, -365, sysutcdatetime()) as MinCreatedUtc) d
where d.MinCreatedUtc < s.CreatedUtc
-- (also tried reversing join order, not shown, no change)
Pruebe algunos consejos (pero N / A para ver):
select distinct SessionId from [User].Session -- 1
where CreatedUtc > dateadd(day, -365, sysutcdatetime())
option (recompile);
select distinct SessionId from [User].Session -- 1
where CreatedUtc > (select dateadd(day, -365, sysutcdatetime()))
option (recompile, optimize for unknown);
select distinct SessionId -- 1
from (select dateadd(day, -365, sysutcdatetime()) as MinCreatedUtc) d
inner loop join [User].Session s
on s.CreatedUtc > d.MinCreatedUtc
option (recompile);
Intente usar Parámetro / Sugerencias (pero N / A para Ver):
declare
@minDate datetime2(7) = dateadd(day, -365, sysutcdatetime());
select distinct SessionId from [User].Session -- 1.2M (adequate)
where CreatedUtc > @minDate;
select distinct SessionId from [User].Session -- 2.96M (great)
where CreatedUtc > @minDate
option (recompile);
select distinct SessionId from [User].Session -- 1.2M (adequate)
where CreatedUtc > @minDate
option (optimize for unknown);
Las estadísticas están actualizadas.
DBCC SHOW_STATISTICS('user.Session', 'IX_User_Session_CreatedUtc') with histogram;
Se muestran las últimas filas del histograma (189 filas en total):
fuente
>= DATEADD(DAY, -365, SYSDATETIME())
el error es en que se basa la estimación>= SYSDATETIME()
. Entonces, técnicamente, la estimación se basa en cuántas filas de la tabla tienen unCreatedUtc
en el futuro. Probablemente sea 0, pero SQL Server siempre redondea 0 hasta 1 para las filas estimadas.Reemplace dateadd () con dateiff () para obtener una aproximación adecuada (30% ish).
Esto parece ser un error similar a MS Connect 630583 .
La opción de recompilación no hace ninguna diferencia.
fuente