Schemas altamente normalizados e camadas de consulta baseadas em views frequentemente geram SQL com muitas cláusulas LEFT JOIN. A maioria é logicamente redundante, pois a tabela unida não contribui para o conjunto de resultados. A eliminação de left join remove essas junções redundantes no nível do otimizador; assim, o banco de dados lê apenas as tabelas necessárias. Em consultas analíticas complexas, esse recurso pode reduzir o tempo de execução em uma ordem de grandeza sem exigir alterações no SQL.
Como funciona
Para cada LEFT JOIN em uma consulta, o PolarDB for MySQL verifica duas condições:
Apenas uma linha da tabela à direita atende à condição de junção para cada linha da tabela à esquerda.
Nenhuma coluna da tabela à direita aparece na lista
SELECTou em qualquer outra parte da consulta.
Se ambas as condições forem verdadeiras, o PolarDB remove a junção do plano de execução. O otimizador aplica essa verificação a cada LEFT JOIN na consulta, o que permite eliminar múltiplas junções redundantes.
Pré-requisitos
Antes de começar, verifique se você tem:
Um cluster PolarDB for MySQL 8.0 com versão de revisão 8.0.1.1.32 ou posterior, ou 8.0.2.2.10 ou posterior
Limitações
A eliminação de left join aplica-se somente quando ambas as condições a seguir são atendidas:
Para cada linha da tabela à esquerda, apenas uma linha da tabela à direita atende à condição de junção.
Nenhuma coluna da tabela à direita é referenciada na instrução SQL fora da própria cláusula
LEFT JOIN.
Ativar a eliminação de left join
Defina o parâmetro loose_join_elimination_mode para controlar a ativação do recurso.
|
Parâmetro |
Nível |
Descrição |
|
|
Global |
Controla a eliminação de left join. Valor padrão: |
Para alterar o parâmetro, consulte Especificar parâmetros de cluster e nó.
O valor padrão REPLICA_ON ativa o recurso apenas em nós somente leitura. Para ativá-lo em todos os nós, incluindo o nó primário, defina o parâmetro como ON.
Verificar com EXPLAIN
Use EXPLAIN para confirmar se a eliminação de left join foi aplicada à consulta.
Antes da otimização
A consulta a seguir une table1 (alias sc), table2 (alias ca) e table3 (alias co). Cada linha em table1 corresponde a apenas uma linha em table2 e table3. Além disso, nenhuma coluna de table2 ou table3 aparece na lista SELECT. Portanto, ambas as condições de eliminação são atendidas.
EXPLAIN
SELECT count(*)
FROM `table1` `sc`
LEFT JOIN `table2` `ca` ON `sc`.`car_id` = `ca`.`id`
LEFT JOIN `table3` `co` ON `sc`.`company_id` = `co`.`id`;
Saída:
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+
| 1 | SIMPLE | sc | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | NULL |
| 1 | SIMPLE | ca | NULL | eq_ref | PRIMARY | PRIMARY | 4 | je_test.sc.car_id | 1 | 100.00 | Using index |
| 1 | SIMPLE | co | NULL | eq_ref | PRIMARY | PRIMARY | 4 | je_test.sc.company_id | 1 | 100.00 | Using index |
+----+-------------+-------+------------+--------+---------------+---------+---------+-----------------------+------+----------+-------------+
As três tabelas aparecem no plano. Tempo de execução: 7,5 segundos.
Após a otimização
Com a eliminação de left join ativada, o otimizador detecta que as junções com table2 e table3 são redundantes. Assim, ele reescreve a consulta para varrer apenas table1.
EXPLAIN
SELECT count(*)
FROM `table1` `sc`
Saída:
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | sc | NULL | ALL | NULL | NULL | NULL | NULL | 2 | 100.00 | NULL |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
Apenas table1 permanece no plano. Tempo de execução: 0,1 segundos — 75 vezes mais rápido que a consulta original.