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:
- Determine quais chaves podem ser usadas para recuperar os registros das tabelas e escolha a melhor para cada tabela.
- Para cada tabela, decida se uma varredura de tabela é melhor do que a leitura em uma tecla. Se houver muitos registros correspondentes ao valor da chave, as vantagens da chave serão reduzidas e a verificação da tabela se tornará mais rápida.
- Determine a ordem na qual as tabelas devem ser unidas quando mais de uma tabela estiver presente na consulta.
- Reescreva as cláusulas WHERE para eliminar o código morto, reduzindo os cálculos desnecessários e alterando as restrições sempre que possível para abrir o caminho para o uso de chaves.
- Eliminar tabelas não utilizadas da associação.
- Determine se as chaves podem ser usadas para
ORDER BY
e GROUP BY
.
- Tente simplificar subconsultas e determinar até que ponto seus resultados podem ser armazenados em cache.
- Mesclar vistas (expanda a referência da vista como uma macro)
Na mesma página, diz o seguinte:
Na terminologia do otimizador do MySQL, toda consulta é um conjunto de junções. O termo junção é usado aqui mais amplamente do que nos comandos SQL. Uma consulta em apenas uma tabela é uma junção degenerada. Embora normalmente não pensemos em ler registros de uma tabela como uma junção, as mesmas estruturas e algoritmos usados com junções convencionais funcionam perfeitamente para resolver a consulta com apenas uma tabela.
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
porque 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.
- contando linhas
- selecionando chaves
- massageando conjuntos de resultados intermitentes
- Ah, sim, fazendo o JOIN real
Você provavelmente teria que coagir a ordem de execução reescrevendo (refatorando) a consulta
Aqui está a primeira consulta que você deu
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y';
Tente reescrevê-lo para avaliar o WHERE primeiro
select count(*)
from table1 a
join (select key_col from table2 where tag='Y') b
on b.key_col=a.key_col;
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.