Consultas analíticas complexas frequentemente incluem operações JOIN desnecessárias para o banco de dados. O recurso de eliminação de JOIN do PolarDB for MySQL detecta e remove esses JOINs redundantes durante a otimização da consulta. Isso reduz E/S, simplifica planos de execução e melhora o desempenho sem alterar os resultados.
A eliminação de JOIN é uma otimização lógica aplicada apenas quando a consulta reescrita é comprovadamente equivalente à original. Todos os seis cenários suportados exigem verificações rigorosas de condições antes da eliminação.
Pré-requisitos
Antes de começar, verifique se você tem:
Um cluster PolarDB for MySQL executando a Cluster Edition ou Standard Edition
MySQL 8.0.2, revisão 8.0.2.2.31.1 ou posterior
Ative a eliminação de JOIN
Controle o recurso com o parâmetro join_elimination_mode. O local de definição do parâmetro determina o nome a usar:
Console do PolarDB: Os parâmetros têm o prefixo
loose_para compatibilidade com o arquivo de configuração do MySQL. Localize e modifiqueloose_join_elimination_mode.Sessão do banco de dados (linha de comando ou cliente): Use o comando
SETsem o prefixoloose_:join_elimination_mode.
|
Parâmetro |
Nível |
Valores válidos |
|
|
Global/Session |
|
Como funciona
O otimizador de consultas analisa as condições de JOIN e os relacionamentos entre tabelas durante o planejamento. Se um JOIN atender às condições de eliminação de um dos seis cenários abaixo, o otimizador removerá o acesso redundante à tabela do plano de execução. A consulta retornará resultados idênticos.
Cenários de otimização
O recurso suporta eliminação automática de JOIN nos seis cenários a seguir.
Cenário 1: LEFT JOINs com condição FALSE constante
Se a condição ON de um LEFT JOIN for sempre FALSE, a junção não produzirá correspondências. O otimizador remove a tabela interna e substitui todas as suas colunas por NULL.
-- Before optimization
SELECT ..., ti1.*, ti2.*, ... FROM ... LEFT JOIN (ti1, ti2, ...) ON FALSE;
-- After optimization
SELECT ..., NULL, NULL, ... FROM ...;
Condição para eliminação: A condição ON é uma expressão FALSE constante, como 1=0 ou FALSE.
Exemplo
-
Prepare o ambiente.
DROP TABLE IF EXISTS orders; CREATE TABLE orders ( order_id INT PRIMARY KEY, customer_id INT, order_date DATE ); DROP TABLE IF EXISTS customers; CREATE TABLE customers ( customer_id INT PRIMARY KEY, customer_name VARCHAR(100) ); INSERT INTO orders VALUES (1, 101, '2023-10-01'); -
Desative a eliminação de JOIN e execute
EXPLAINpara visualizar o plano não otimizado.SET SESSION join_elimination_mode = 'OFF'; EXPLAIN SELECT o.*, c.* FROM orders o LEFT JOIN customers c ON FALSE; SHOW WARNINGS;Saída:
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1003 | /* select#1 */ select `testdb`.`o`.`order_id` AS `order_id`,`testdb`.`o`.`customer_id` AS `customer_id`,`testdb`.`o`.`order_date` AS `order_date`,`testdb`.`c`.`customer_id` AS `customer_id`,`testdb`.`c`.`customer_name` AS `customer_name` from `testdb`.`orders` `o` left join `testdb`.`customers` `c` on(false) where true | +-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -
Ative a eliminação de JOIN e execute a mesma consulta.
SET SESSION join_elimination_mode = 'ON'; EXPLAIN SELECT o.*, c.* FROM orders o LEFT JOIN customers c ON FALSE; SHOW WARNINGS;Saída:
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Level | Code | Message | +-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Note | 1003 | /* select#1 */ select `testdb`.`o`.`order_id` AS `order_id`,`testdb`.`o`.`customer_id` AS `customer_id`,`testdb`.`o`.`order_date` AS `order_date`,NULL AS `customer_id`,NULL AS `customer_name` from `testdb`.`orders` `o` | +-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+A tabela
customersnão aparece mais na consulta reescrita, pois a junção foi eliminada.
Cenário 2: LEFT JOINs em chaves únicas que não afetam o resultado
Se a tabela interna de um LEFT JOIN não for referenciada em outra parte da consulta e a junção não alterar o número de linhas retornadas da tabela externa, será seguro removê-la.
-- Before optimization
SELECT to1.*, to2.*, ..., tom.*
FROM to1, to2, ..., tom LEFT JOIN (ti1, ti2, ..., tin) ON cond_on
WHERE cond_where ...
-- After optimization
SELECT to1.*, to2.*, ..., tom.*
FROM to1, to2, ..., tom
WHERE cond_where ...
Condições para eliminação:
Tabela interna não referenciada: Nenhuma coluna das tabelas internas (
ti1, ti2, ..., tin) aparece fora doLEFT JOINe de sua condiçãoON.-
A junção não afeta a cardinalidade da tabela externa: Uma das seguintes condições deve ser verdadeira:
A junção é única: cada linha na tabela externa corresponde a, no máximo, uma linha na tabela interna.
A junção pode produzir duplicatas, mas operações subsequentes da consulta cancelam seu efeito. Por exemplo, a junção está dentro de uma cláusula
EXISTSouIN(um SEMI JOIN), ou a subconsulta contémGROUP BY,LIMITou funções de janela.Uso recursivo das duas condições anteriores.
Cenário 3: Autojunções
Quando uma tabela (ou sua tabela derivada) se une a si mesma usando um INNER JOIN e condições específicas são atendidas, o otimizador identifica uma cópia como redundante e a remove.
Tabela base unida a tabela base:
-- Before optimization
SELECT target.*, source.* FROM t1 AS target JOIN t1 AS source WHERE target.uk = source.uk;
-- After optimization
SELECT source.*, source.* FROM source WHERE source.uk = source.uk;
Tabela derivada unida a tabela derivada:
-- Before optimization
SELECT target.*, source.*
FROM (SELECT * FROM t1) target
JOIN (SELECT * FROM t1 WHERE t1.a > 1) source
WHERE target.uk = source.uk;
-- After optimization
SELECT source.*, source.*
FROM (SELECT * FROM t1 WHERE t1.a > 1) source
WHERE source.uk = source.uk;
Tabela base unida a tabela derivada:
-- Before optimization
SELECT target.*, source.*
FROM t1 target
JOIN (SELECT * FROM t1 WHERE t1.a > 1) source
WHERE target.uk = source.uk;
-- After optimization
SELECT source.*, source.*
FROM (SELECT * FROM t1 WHERE t1.a > 1) source
WHERE source.uk = source.uk;
Condições para eliminação:
Relação de subconjunto: O conjunto de resultados de
sourcedeve ser um subconjunto do conjunto de resultados detarget.Disponibilidade de colunas: Todas as colunas referenciadas de
targettambém devem existir emsource.-
Junção por chave única: A condição de
JOINdeve usar uma comparação de igualdade em uma chave única ou chave primária na tabelatarget. Isso garante que cada linha desourcecorresponda a, no máximo, uma linha detarget. Assim, removertargetnão altera a contagem de linhas ou os resultados.Caso especial: Se não houver condição de igualdade de chave única, a eliminação se aplica apenas quando o conjunto de resultados de
targetcontém zero ou uma linha.
Cenário 4: Auto-semi-joins
Quando uma tabela passa por uma semi-join consigo mesma (expressa como uma cláusula IN ou EXISTS), o otimizador pode eliminar a tabela interna e mesclar suas condições na consulta externa.
Com condição de igualdade de coluna única:
-- Before optimization
SELECT source.*
FROM t1 AS source
WHERE EXISTS (
SELECT * FROM t1 AS target
WHERE source.uk = target.uk AND target.a > 1
);
-- After optimization
SELECT source.* FROM t1 AS source WHERE source.uk = source.uk AND source.a > 1;
Sem condição de igualdade de coluna única:
-- Before optimization
SELECT source.*
FROM t1 AS source
WHERE EXISTS (SELECT * FROM t1 AS target WHERE source.a = target.a);
-- After optimization
SELECT source.* FROM t1 AS source WHERE source.a = source.a;
Condições para eliminação:
Relação de subconjunto: O conjunto de resultados de
sourcedeve ser um subconjunto do conjunto de resultados detarget.Disponibilidade de colunas: Todas as colunas referenciadas de
targettambém devem existir emsource.-
Uma das seguintes condições também deve ser verdadeira:
-
Junção por chave única: A condição de
JOINusa uma comparação de igualdade em uma chave única ou chave primária emtarget. Isso assegura que cada linha desourcecorresponda a, no máximo, uma linha detarget.Caso especial: Sem igualdade de chave única, a eliminação se aplica apenas quando o conjunto de resultados de
targetcontém zero ou uma linha.
Todas as condições de junção são comparações de igualdade (
target.col = source.col) conectadas porAND.
-
Cenário 5: Junções por chave estrangeira
Quando existe uma restrição de chave estrangeira (FK) entre duas tabelas e a consulta referencia apenas colunas da tabela filha (a tabela com a FK), a junção com a tabela pai é redundante. A restrição de FK já garante que cada linha filha tenha uma linha pai correspondente.
CREATE TABLE target (a INT PRIMARY KEY);
CREATE TABLE source (a INT, FOREIGN KEY (a) REFERENCES target(a));
-- Before optimization
SELECT target.a, source.a FROM target, source WHERE target.a = source.a;
-- After optimization
SELECT source.a, source.a FROM source WHERE source.a = source.a;
Condições para eliminação:
Referências substituíveis à tabela pai: É possível substituir todas as colunas da tabela pai pelas colunas de FK correspondentes na tabela filha. Na prática, isso significa que apenas a chave de junção da tabela pai é referenciada.
Condição de junção baseada na chave estrangeira: A condição de
JOINé uma igualdade entre a coluna de FK da tabela filha e a coluna de chave primária ou chave única da tabela pai.Chave estrangeira NOT NULL: A coluna de FK na tabela filha é definida como
NOT NULL, o que garante que cada linha filha tenha uma linha pai correspondente.
Cenário 6: Semi-joins por chave estrangeira
Quando uma cláusula EXISTS ou IN verifica a existência de um registro correspondente na tabela pai com base em um relacionamento de FK, a verificação é redundante. A restrição de FK já garante que a correspondência exista. O otimizador elimina a subconsulta SEMI JOIN.
CREATE TABLE target (a INT PRIMARY KEY);
CREATE TABLE source (a INT, FOREIGN KEY (a) REFERENCES target(a));
-- Before optimization
SELECT source.a FROM source WHERE EXISTS (SELECT * FROM target WHERE target.a = source.a);
-- After optimization
SELECT source.a FROM source WHERE source.a = source.a;
Condições para eliminação: As mesmas três condições do Cenário 5 — referências ao pai substituíveis, condição de junção baseada em FK e coluna de FK NOT NULL.
Perguntas frequentes
Por que minha consulta não é otimizada após ativar join_elimination_mode?
Verifique os itens a seguir nesta ordem:
Versão: Confirme se a versão do seu cluster atende aos requisitos em Pré-requisitos.
Correspondência de cenário: Verifique se sua instrução SQL e o esquema da tabela satisfazem as condições de eliminação para um dos seis cenários acima.
Lista SELECT: Para cenários de LEFT JOIN e junção por chave estrangeira, a lista
SELECTnão deve referenciar nenhuma coluna da tabela a ser eliminada.Complexidade da consulta: Certas estruturas de subconsultas aninhadas podem impedir a eliminação. Simplifique a consulta para verificar se a própria estrutura é o bloqueio.
A eliminação de JOIN afeta a correção da consulta?
Não. A eliminação de JOIN é uma otimização lógica aplicada apenas quando a consulta reescrita é comprovadamente equivalente à original. Ela altera o caminho de execução, não a semântica ou os resultados. Todos os seis cenários exigem verificações rigorosas de condições antes da aplicação da eliminação.