Tengo una consulta que usa una función en el predicado, algo como esto:
commentType = 'EL'
AND commentDateTime >= DATEADD(month,datediff(month,0,getdate()) - 13,0)
Tengo un índice filtrado en commentType que tiene 40K filas y cuando ejecuto la consulta, el número estimado de filas para Index Seek es muy preciso (alrededor de 11K), pero para el siguiente paso (operador de clasificación) ignora por completo las estadísticas y solo estima el número total de filas en el índice filtrado.
¿Por qué está pasando esto? Sé lo básico sobre la sargabilidad , y lo probé solo por razones de cordura, reemplazando el dateadd por una fecha real (01-01-2014) y listo ... El tipo comenzó a adivinar el número de filas correctamente ...
¿Por qué sucede esto y cómo puedo solucionarlo? No puedo pasar una fecha fija ...
sql-server
index
statistics
MrKudz
fuente
fuente
DATEADD(month,datediff(month,0,getdate()) - 13,0)
no tiene sentido para mi ¿Qué intentas hacer con esto? ¿Se podría mejorar / simplificar?DATEADD(month, -13, DATEADD(day, 1-DATEPART(day, SYSDATETIME()))
ver si hay alguna diferencia?(commentType, commentDate)
, ¿se comporta mejor allí? Es solo que los índices filtrados a veces pueden informar erróneamente las estimaciones en diferentes puntos de los planes. La estimación parece completa al informar el número total en el índice filtrado, pero en realidad es que el plan se muestra incorrectamente.Respuestas:
Creo que sus estimaciones son incorrectas debido a un error del estimador que intercambia dos de los argumentos DATEDIFF. Hablo de esto aquí:
Una solución alternativa es calcular el primer día de hace 13 meses sin usar DATEDIFF (2008+):
No estoy seguro de que abordará la estimación (no he probado con índices filtrados, y no estoy seguro de qué está haciendo realmente el tipo o por qué tiene una estimación diferente sin el plan y / o el resto de la consulta )
La solución que Microsoft recomienda es usar TF 4199, pero no estoy tan seguro de que sea lo que deba hacer aquí:
Otra opción sería asegurarse de estar en el último SP / CU absoluto para cualquier versión de SQL Server que esté utilizando, ya que afirman que está solucionado en el siguiente artículo de KB (aunque esto aún requerirá el uso de TF 4199 a menos que esté en 2014 o mejor):
La solución se puede obtener con las siguientes compilaciones:
(La próxima vez, incluya los resultados de
SELECT @@VERSION
en su pregunta).Notaré que el artículo de KB dice que DATEDIFF puede subestimar el número de filas, que es lo contrario de lo que está sucediendo en su escenario. Eso no significa que las correcciones no se apliquen a usted; Creo que la redacción del artículo de KB es inexacta, ya que las estimaciones pueden ir en cualquier dirección dependiendo de los datos y el rango que esté viendo.
Mi publicación de blog anterior confirmó que el intercambio ya no se produce en 2014 o más. Para estar seguro, probablemente simplemente eliminaría DATEDIFF de su predicado y usaría un método diferente para calcular el comienzo de su rango. No sugiero la exageración de 4199 o el uso de SQL dinámico para evitar el intercambio incorrecto.
fuente