Existe uma diferença de desempenho entre essas duas consultas de exemplo?
Consulta 1:
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y'
Consulta 2;
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
and b.tag = 'Y'
Observe que a única diferença é a colocação da condição suplementar; o primeiro usa uma WHERE
cláusula e o segundo adiciona a condição à ON
cláusula.
Quando executo essas consultas no meu sistema Teradata, os planos de explicação são idênticos e a etapa JOIN mostra a condição adicional em cada caso. No entanto, nesta questão do SO referente ao MySQL, uma das respostas sugeriu que o segundo estilo é preferido porque o WHERE
processamento ocorre após as junções.
Existe uma regra geral a seguir ao codificar consultas como esta? Acho que deve ser dependente da plataforma, pois obviamente não faz diferença no meu banco de dados, mas talvez isso seja apenas um recurso do Teradata. E se for dependente da plataforma, eu gostaria muito de obter algumas referências de documentação; Eu realmente não sei o que procurar.
fonte
Respostas:
De acordo com o Capítulo 9 (Analisador e Otimizador), Página 172 do Livro Entendendo o MySQL Internals por Sasha Pachev
aqui está o detalhamento da avaliação de uma consulta como as seguintes tarefas:
ORDER BY
eGROUP BY
.Na mesma página, diz o seguinte:
EPÍLOGO
Por causa das chaves presentes, da quantidade de dados e da expressão da consulta, o MySQL Joins às vezes pode fazer coisas para o nosso próprio bem (ou para nos vingar) e apresentar resultados que não esperávamos e que não podemos explicar rapidamente.
Eu escrevi sobre essa estranheza antes
Jan 23, 2013
: Problema com consultas UPDATE aninhadasFeb 22, 2011
: Problema com a subconsulta do MySQLporque o MySQL Query Optimizer poderia dispensar certas chaves durante a avaliação da consulta.
O comentário de @ Phil me ajuda a ver como postar esta resposta (+1 no comentário de @ Phil)
O comentário do @ ypercube (+1 para este também) é uma versão compacta do meu post porque o Query Optimizer do MySQL é primitivo. Infelizmente, tem que ser porque lida com mecanismos de armazenamento externos.
CONCLUSÃO
Quanto à sua pergunta real, o MySQL Query Optimizer determinaria as métricas de desempenho de cada consulta quando for concluída.
Você provavelmente teria que coagir a ordem de execução reescrevendo (refatorando) a consulta
Aqui está a primeira consulta que você deu
Tente reescrevê-lo para avaliar o WHERE primeiro
Isso definitivamente alteraria o plano EXPLAIN. Pode produzir resultados melhores ou piores.
Certa vez, respondi a uma pergunta no StackOverflow onde apliquei essa técnica. O EXPLAIN foi horrendo, mas o desempenho foi dinamite. Funcionou apenas devido à presença dos índices corretos e ao uso de LIMIT em uma subconsulta .
Assim como ocorre com os preços das ações, quando se trata de consultas e de tentar expressá-las, aplicam-se restrições, os resultados podem variar e o desempenho passado não é indicativo de resultados futuros.
fonte
Para a Oracle, como o mySQL possui uma descrição extensa, temos 2 maneiras de alto nível de alavancar o otimizador.
O primeiro é a Otimização Baseada em Regras (ou RBO). O Oracle possui 15 regras definidas em cada consulta que analisa as tentativas de seguir em uma ordem definida. Se não puder gerar uma consulta otimizada a partir da regra 1, ela avançará para a regra 2 e seguirá em frente até atingir a regra 15.
para obter mais informações: https://docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm
Isso afeta os kernels do Oracle RDBMS da 11.1 e abaixo que não foram convertidos no Cost Based Optimizer (também conhecido como CBO). O Oracle 11.2 e posterior requerem o otimizador de CBO, mas podem forçar IDs de SQL específicos a otimizar no método RBO antigo, se o usuário desejar.
Em vez disso, o CBO para Oracle 11.1+ faz vários planos de execução para o mesmo ID SQL e executa o que tem o menor custo total previsto. Ele aproveita grande parte da lógica da RBO, mas analisa as estatísticas da tabela para criar custos dinâmicos do plano de execução para cada operação que o banco de dados precisa realizar para fornecer seus dados ao usuário final. Executar varreduras completas de tabelas em tabelas muito grandes é realmente caro; executar verificações completas de tabela em uma tabela com 10 linhas é barato. Na RBO, essas operações foram consideradas iguais.
para obter mais informações: https://oracle-base.com/articles/misc/cost-based-optimizer-and-database-statistics
Para seu exemplo de consulta específico: a Oracle provavelmente analisará as informações para fazer planos de execução diferentes e, portanto, um será tecnicamente melhor que o outro. No entanto, isso pode ser uma diferença mínima. Observando isso, o Oracle RBO e o CBO gostariam de consultar mais 1 porque está executando em uma junção em menos condições e filtrando uma coluna específica da tabela temporária criada a partir da junção.
fonte
Se você tiver duas consultas e acha que elas são equivalentes, pode acontecer o seguinte:
existem diferentes planos de execução. Temos duas subcasas aqui.
2.1 As consultas têm planos de execução diferentes, mas os dois planos apresentam desempenho igualmente bom. Tudo bem também. Não é necessário que, para consultas equivalentes, o mesmo plano seja gerado. Mas o desempenho deve ser igual. E novamente esperamos que seja o melhor possível.
2.2 As consultas têm planos de execução diferentes e um plano é melhor que o outro. Novamente, temos subcasas:
2.2.1 Os planos são diferentes porque as consultas não são equivalentes. Portanto, verifique com cuidado se eles são realmente equivalentes. No seu caso, eles são realmente equivalentes.
2.2.2 Os planos são diferentes, mas as consultas são equivalentes. Isso significa que o otimizador não está maduro o suficiente. Em um mundo perfeito, com otimizadores perfeitos, isso não deve acontecer. Portanto, sim, depende da plataforma e você precisa estudar documentos específicos da plataforma para descobrir por que isso acontece.
2.2.3 Os planos são diferentes, as consultas são equivalentes, o software do banco de dados possui um bug.
fonte