Forçando um UNION em um OR para otimização em SQL Server 2000
-
21-08-2019 - |
Pergunta
Como posso obter uma consulta que usa um OR na cláusula WHERE para dividir-se em duas consultas com a União durante a compilação? Se eu reescrevê-lo manualmente, a consulta usando o UNION é 100x mais rápido que a única consulta, porque ele pode usar eficazmente índices diferentes em cada consulta do sindicato. Existe alguma maneira eu posso fazer o otimizador de usar essa abordagem?
Eu tenho uma consulta que é algo como isto:
select columnlist
from table1
join table2 on joincond2
join table3 on joincond3
where conditions1
and ((@param1 is null and cond3a) or (cond3b))
Onde ColumnList, joincond2, joincond3 e conditions1 são todas expressões mais longas. O kicker é que apenas uma das condições no OR é sempre verdadeiro.
A primeira vez que pensei que eu poderia simplesmente reescrevê-lo a fazer a união, mas então eu estou repetindo ColumnList, joincond2, joincond3 e conditions1, que é 20 ou mais linhas de SQL que podem precisar de muita manutenção no futuro. Existe uma dica que eu posso fornecer ou algum melhor maneira de escrever a cláusula WHERE? Agradecemos antecipadamente.
Solução
Você pode agrupar
select columnlist
from table1
join table2 on joincond2
join table3 on joincond3
para uma visualização, e depois uso união.
mas se você pode migrar para sql2005 / 8, você pode usar expressão de tabela comum.
with cte ( columnlist )
as (
select columnlist
from table1
join table2 on joincond2
join table3 on joincond3 )
select columnlist from cte where ...
union
select columnlist from cte where ...
Outras dicas
Tente adicionar OPÇÃO (RECOMPILE) para a consulta. Se está em um procedimento armazenado, em seguida, adicionar WITH RECOMPILE para isso também. Pode ser que a primeira vez que você executar a consulta SQL Server vem com um plano e armazena em cache-lo, mas, em seguida, na segunda vez ele ainda está usando o plano de consulta antigo (e agora pobres).
Você vai tomar uma batida menor, porque ele vai precisar recompilar cada vez que você usar a consulta, mas será minúscula em comparação com o uso de um plano de pobres.
EDIT: Eu li que usando WITH RECOMPILE em um procedimento armazenado no SQL 2000 nem sempre funciona corretamente. O bug foi supostamente corrigido no SQL 2005. Eu nunca encontrei o bug pessoalmente, então eu não sei qual é o problema exato é com ele. Experimentá-lo embora.