Substituição de valor nulo em constante
Pergunta
Por diversão, eu tenho jogado com o otimizador embutido para o Oracle no Toad hoje. Uma das otimizações que sugere é o seguinte
AND emp.pay_type = NVL('FT', UID)
Ao invés de
AND emp.pay_type = 'FT'
Estou confuso com o que está acontecendo aqui e, por causa disso, confuso sobre por que isso melhoraria o desempenho. Como FT é um literal de corda na consulta SQL e, portanto, nunca é nulo, por que isso faria alguma diferença? Acho que tem algo a ver com o índice existente em campo, mas não consigo encontrar nada nos documentos do Oracle.
Solução
Esse é um conselho estranho. A função NVL funciona assim:
NVL(exp1, val1)
Se 'Exp1' não for nulo, ele é devolvido; Caso contrário, 'val1' será devolvido.
Como 'ft' no exemplo não pode ser nulo, não há benefício em usar a função NVL e uma pequena penalidade de desempenho (pelo menos para o otimizador descobrir que o NVL é redundante; talvez uma penalidade de execução se o otimizador não funcionar fora que o NVL é redundante).
Se a condição dizia:
E emp.pay_type = nvl ("ft", uid)
Então pode haver um benefício; Aqui temos um identificador delimitado (o nome da coluna entre aspas duplas) e o valor da coluna talvez possa ser nulo; A chamada NVL garante que Null seja devolvido apenas se "ft" for nulo e Uid é nulo. Uid é, obviamente, um identificador regular.
Pode fazer sentido se a condição dizia:
AND emp.pay_type = NVL(UID, 'FT')
Agora, se o valor UID for nulo, um valor padrão 'ft' será usado como o Pay_type correspondente.
Outras dicas
Eu aceitaria as "sugestões de otimização" do Toad com enormes grãos de sal. Eu os chamo de método de otimização "espingarda" - atire muitos bits diferentes no alvo e veja qual deles atinge, de alguma forma :)
Enfim, a diferença entre
AND emp.pay_type = NVL('FT', UID)
e
AND emp.pay_type = 'FT'
É que, no segundo caso, o otimizador pode usar as estatísticas do histograma na coluna (se foram reunidas) para obter uma estimativa mais precisa do número de linhas correspondentes. Quando o NVL é usado, no entanto, o otimizador (acredito) não detectará que ele pode ignorar o NVL e, portanto, não verificará o histograma quanto ao valor.
Este não é um método de otimização que eu geralmente usaria. Existem maneiras melhores de controlar o caminho de execução de uma consulta (dicas, por exemplo). Em particular, esse método falharia se eles melhorassem a CBO para procurar e otimizar o código redundante como NVL([literal value],[anything])
para [literal value]
.
O que o Plano de Explicação da Oracle diz sobre as duas consultas?