Creé una función que acepta una fecha de inicio y finalización, siendo la fecha de finalización opcional. Luego escribí un CASEen el filtro para usar la fecha de inicio si no se pasa ninguna fecha de finalización.
CASE WHEN @dateEnd IS NULL
THEN @dateStart
ELSE @dateEnd
END
Cuando llamo a la función para el mes más reciente de los datos:
SELECT * FROM theFunction ('2013-06-01', NULL)
... la consulta se cuelga. Si especifico la fecha de finalización:
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
... el resultado se devuelve normalmente. Saqué el código de la función y lo ejecuté bien dentro de una ventana de consulta. No puedo duplicar el problema del violín tampoco. Una consulta como:
SELECT * FROM theFunction ('2013-04-01', '2013-06-01')
... también funciona bien.
¿Hay algo en la consulta (a continuación) que pueda causar que la función se bloquee cuando NULLse pasa un para la fecha de finalización?
- Plan de ejecución para
SELECT * FROM theFunction ('2013-06-01', '2013-06-01') - Plan estimado para
SELECT * FROM theFunction ('2013-06-01', NULL)
sql-server
sql-server-2008-r2
Kermit
fuente
fuente

CASEconCOALESCE(@dateEnd,@dateStart), ¿sigue apareciendo el problema?ISNULL()?SELECT task_state FROM sys.dm_os_tasks WHERE session_id = xmuestra? Si pasa mucho tiempo sin estar en elRUNNINGestado, ¿qué tipos de espera está recibiendo esa sesiónsys.dm_os_waiting_tasks?COALESCE.ISNULLarreglado.Respuestas:
Parte de su consulta inicial es la siguiente.
Esa sección del plan se muestra a continuación
Su consulta revisada
BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)tiene esto para la misma combinaciónLa diferencia parece ser que se
ISNULLsimplifica aún más y, como resultado, obtienes estadísticas de cardinalidad más precisas en la próxima unión. Esta es una función con valores de tabla en línea y la está llamando con valores literales para que pueda hacer algo así.Y como hay un predicado de equi join,
b.[Date] = a.del plan también muestra un predicado de igualdadb.[Date] = '2013-06-01'. Como resultado,28,393es probable que la estimación de cardinalidad de las filas sea bastante precisa.Para la versión
CASE/COALESCEcuando@dateStarty@dateEndson el mismo valor, entonces simplifica OK a la misma expresión de igualdad y proporciona el mismo plan, pero cuando@dateStart = '2013-06-01'y@dateEnd IS NULLsolo va tan lejos comoque también se aplica como un predicado implícito en
ColleagueList. El número estimado de filas esta vez es79.8filas.La próxima unión es
colleagueTimees una3,249,590tabla de filas que (de nuevo) aparentemente es un montón sin índices útiles.Esta discrepancia en las estimaciones afecta la elección de combinación utilizada. El
ISNULLplan elige una combinación hash que solo escanea la tabla una vez. ElCOALESCEplan elige una unión de bucles anidados y estima que solo tendrá que escanear la tabla una vez y poder poner en cola el resultado y reproducirlo 78 veces. es decir, estima que los parámetros correlacionados no cambiarán.Por el hecho de que el plan de bucles anidados seguía funcionando después de dos horas, esta suposición de un solo escaneo en contra
colleagueTimeparece ser muy inexacta.En cuanto a por qué el número estimado de filas entre las dos uniones es mucho menor, no estoy seguro sin poder ver las estadísticas en las tablas. La única forma en que logré sesgar los recuentos de filas estimados tanto en mis pruebas fue agregando una carga de
NULLfilas (esto redujo el recuento de filas estimado a pesar de que el número real de filas devueltas permaneció igual).El recuento de filas estimado en el
COALESCEplan con mis datos de prueba fue del orden deO en SQL
pero esto no cuadra con su comentario de que la columna no tiene
NULLvalores.fuente
NULLvalores para fechas en ninguna de esas tablas.dbono aparece en la lista. Solo otros esquemas que no uso.Parece que hubo un problema con los tipos de datos.
ISNULLsolucionado el problema (gracias ypercube ). Después de un poco de investigación,COALESCEes el equivalente a laCASEdeclaración que estaba usando:Paul White explica que:
Para evitar problemas de tipo de datos, parece que
ISNULLes la función apropiada para tratar solo con dos expresiones.Extractos del plan XML
El plan XML que usa la
CASEexpresión 2 esNULL:Plan XML utilizando
CASE, la expresión 2 es una fecha:El plan XML que usa la
ISNULLexpresión 2 esNULL:Plan XML utilizando
ISNULL, la expresión 2 es una fecha:fuente
SELECT * FROM theFunction ('2013-06-01', '2013-06-01'). La expresión datatype sigue siendo la misma. Y ambos parámetros son dedatetipo de datos de todos modos. ¿Puedes ver los planes de ejecución?NULL.CASEtambién no tuvo efecto, la consulta aún se cuelga.ISNULLmiradas del plan como Simplifica mejor. Tiene un predicado de igualdad simple en ColleagueList de[Date]='2013-06-01'mientras que elCASEque tiene un predicado en[Date]>='2013-06-01' AND [Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END AND PROBE([Bitmap1067],[Date]). Las filas estimadas que salen de esa unión son 28,393 para laISNULLversión, pero mucho más bajas79.8para laCASEversión que afecta la elección de la unión más adelante en el plan. No estoy seguro de por qué habría tanta discrepancia.