Criei uma função que aceita uma data de início e término, sendo a data final opcional. Em seguida, escrevi um CASE
no filtro para usar a data de início se nenhuma data de término for passada.
CASE WHEN @dateEnd IS NULL
THEN @dateStart
ELSE @dateEnd
END
Quando chamo a função para o mês mais recente dos dados:
SELECT * FROM theFunction ('2013-06-01', NULL)
... a consulta trava. Se eu especificar a data final:
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
... o resultado é retornado normalmente. Tirei o código da função e executei-o bem dentro de uma janela de consulta. Também não posso duplicar a questão. Uma consulta como:
SELECT * FROM theFunction ('2013-04-01', '2013-06-01')
... também funciona bem.
Existe alguma coisa na consulta (abaixo) que possa estar causando a interrupção da função quando a NULL
é passada para a data final?
- Plano de execução para
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
- Plano estimado para
SELECT * FROM theFunction ('2013-06-01', NULL)
CASE
porCOALESCE(@dateEnd,@dateStart)
, o problema ainda aparece?ISNULL()
?SELECT task_state FROM sys.dm_os_tasks WHERE session_id = x
mostra? Se ele passa muito tempo fora doRUNNING
estado, em que tipos de espera está entrando a sessãosys.dm_os_waiting_tasks
?COALESCE
.ISNULL
consertou.Respostas:
Parte da sua consulta inicial é a seguinte.
Essa seção do plano é mostrada abaixo
Sua consulta revisada
BETWEEN @dateStart AND ISNULL(@dateEnd,@dateStart)
tem isso para a mesma associaçãoA diferença parece ser que
ISNULL
simplifica ainda mais e, como resultado, você obtém estatísticas de cardinalidade mais precisas na próxima associação. Esta é uma função com valor de tabela embutida e você a está chamando com valores literais para que ela possa fazer algo parecido.E como há um predicado de equi join,
b.[Date] = a.d
o plano também mostra um predicado de igualdadeb.[Date] = '2013-06-01'
. Como resultado, a estimativa de cardinalidade das28,393
linhas provavelmente será bastante precisa.Para a versão
CASE
/COALESCE
quando@dateStart
e@dateEnd
tem o mesmo valor, simplifica OK para a mesma expressão de igualdade e fornece o mesmo plano, mas quando@dateStart = '2013-06-01'
e@dateEnd IS NULL
só vai atéque também se aplica como predicado implícito em
ColleagueList
. O número estimado de linhas dessa vez é de79.8
linhas.A próxima junção é:
colleagueTime
é uma3,249,590
tabela de linhas que é (novamente) aparentemente uma pilha sem índices úteis.Essa discrepância nas estimativas afeta a escolha de junção usada. O
ISNULL
plano escolhe uma junção de hash que apenas varre a tabela uma vez. OCOALESCE
plano escolhe uma junção de loops aninhados e estima que ainda será necessário varrer a tabela uma vez e poder colocar o resultado em spool e reproduzi-lo 78 vezes. isto é, estima que os parâmetros correlacionados não serão alterados.Pelo fato de o plano de loops aninhados ainda estar em andamento após duas horas, é
colleagueTime
provável que essa suposição de uma única varredura seja altamente imprecisa.Quanto ao motivo pelo qual o número estimado de linhas entre as duas junções é muito menor, não tenho certeza sem poder ver as estatísticas nas tabelas. A única maneira de conseguir distorcer as contagens estimadas de linhas que muito em meus testes foi adicionar uma carga de
NULL
linhas (isso reduziu a contagem estimada de linhas, mesmo que o número real de linhas retornadas permanecesse o mesmo).A contagem estimada de linhas no
COALESCE
plano com meus dados de teste foi da ordem deOu no SQL
mas isso não corresponde ao seu comentário de que a coluna não tem
NULL
valores.fonte
NULL
valores para datas em nenhuma dessas tabelas.dbo
não está listado. Apenas outros esquemas que eu não uso.Parece que houve um problema com os tipos de dados.
ISNULL
Corrigido o problema (obrigado ypercube ). Após algumas pesquisas,COALESCE
é o equivalente àCASE
afirmação que eu estava usando:Paul White explica que:
Para evitar problemas de tipo de dados, parece
ISNULL
ser a função apropriada a ser usada para lidar com apenas duas expressões.Trechos do plano XML
O plano XML usando
CASE
, expressão 2 éNULL
:Plano XML usando
CASE
, expressão 2 é uma data:O plano XML usando
ISNULL
, expressão 2 éNULL
:Plano XML usando
ISNULL
, expressão 2 é uma data:fonte
SELECT * FROM theFunction ('2013-06-01', '2013-06-01')
. O tipo de dados da expressão ainda é o mesmo. E ambos os parâmetros são dodate
tipo de dados de qualquer maneira. Você pode visualizar os planos de execução?NULL
.CASE
também não teve efeito, a consulta ainda trava.ISNULL
plano parece simplificar melhor. Ele tem um predicado de igualdade simples no ColleagueList,[Date]='2013-06-01'
enquanto queCASE
aquele tem um predicado[Date]>='2013-06-01' AND [Date]<=CASE WHEN (1) THEN '2013-06-01' ELSE NULL END AND PROBE([Bitmap1067],[Date])
. As linhas estimadas que saem dessa junção são 28.393 para aISNULL
versão, mas muito mais baixas79.8
para aCASE
versão que afeta a opção de junção posteriormente no plano. Não sei por que haveria tal discrepância.