O pushdown de condição de junção acelera consultas complexas com tabelas derivadas ao mover condições de junção externas para o escopo de execução da tabela derivada. Esse mecanismo permite filtragem baseada em índice em vez de materialização completa e reduz o tempo de execução da consulta de dezenas de segundos para milissegundos.
Pré-requisitos
Antes de começar, verifique se você tem:
Um cluster PolarDB for MySQL 8.0 com a versão de revisão 8.0.2.2.10 ou posterior
Como funciona
No MySQL padrão, uma tabela derivada (também chamada de visualização inline) não mesclável na consulta externa — por exemplo, uma que usa GROUP BY, funções de agregação ou funções de janela — exige materialização completa antes da execução da junção externa. A materialização completa torna-se lenta quando a tabela derivada contém grande volume de dados.
Com o pushdown de condição de junção, o otimizador de consultas do PolarDB detecta referências a colunas da tabela derivada em condições de junção externas e reescreve o plano de execução para aplicar essa condição antecipadamente, dentro da própria tabela derivada. Dessa forma, a tabela derivada usa um índice para filtrar linhas antes da materialização e reduz o volume de dados processados pela consulta externa.
O otimizador usa cálculo de custo para decidir se o pushdown de uma condição gera um plano mais eficiente. O pushdown ocorre apenas quando a filtragem indexada elimina uma parcela significativa das linhas.
Quando usar o pushdown de condição de junção
O pushdown de condição de junção é mais eficaz quando as duas condições abaixo são verdadeiras:
Junções em loop aninhado com colunas internas indexadas: A consulta externa e a tabela derivada usam junção em loop aninhado, e a coluna de junção na tabela derivada possui índice. O pushdown da condição de junção permite que a tabela derivada use esse índice para materializar apenas as linhas correspondentes.
Condições de alta seletividade: O pushdown da condição de junção filtra uma grande fração das linhas. Quanto mais dados o índice eliminar, maior será o ganho de desempenho.
Ativar o pushdown de condição de junção
Use os parâmetros a seguir para controlar o pushdown de condição de junção. Para obter instruções sobre como definir parâmetros, consulte Configure parâmetros de cluster e nó.
|
Parâmetro |
Nível |
Descrição |
|
|
Global e sessão |
Controla a ativação do pushdown de condição de junção. Defina |
|
|
Global |
Especifica quais nós usam o pushdown de condição de junção. Valores válidos: |
Para desativar completamente o pushdown de condição de junção, defina join_predicate_pushdown=OFF em loose_polar_optimizer_switch. Para ativá-lo em todos os nós, em vez de apenas nos nós somente leitura, defina loose_join_predicate_pushdown_opt_mode como ON.
Exemplo
O exemplo a seguir mostra uma consulta que une três tabelas derivadas. A tabela derivada os usa uma função de janela (ROW_NUMBER() OVER), portanto não pode ser mesclada na consulta externa e exige materialização.
Antes do pushdown
Sem o pushdown de condição de junção, os passa por materialização completa: todas as linhas correspondentes ao filtro update_date são verificadas e agregadas antes da aplicação da condição de junção od.id = os.detail_id. Essa consulta leva aproximadamente 65 segundos.
SELECT *
FROM (
SELECT *
FROM sample_table.tb_order
WHERE create_date >= DATE_SUB(CAST('2022-12-05 15:12:05' AS datetime), INTERVAL 5 MINUTE)
AND product_type IN (2, 4)
) o
LEFT JOIN (
SELECT *
FROM sample_table.tb_order_detailed
WHERE update_time >= DATE_SUB('2022-12-05 15:12:05', INTERVAL 50 MINUTE)
) od
ON o.order_id = od.order_id
LEFT JOIN (
SELECT t.*, row_number() OVER (PARTITION BY detail_id ORDER BY update_date DESC) AS rn
FROM sample_table.tb_order_sku t
WHERE update_date >= DATE_SUB('2022-12-05 15:12:05', INTERVAL 50 MINUTE)
AND coalesce(product_type, '0') <> '5'
) os
ON od.id = os.detail_id;
Após o pushdown
Com o pushdown de condição de junção ativado, o otimizador reescreve o plano para mover od.id = detail_id para dentro da tabela derivada os, expresso como uma junção lateral. A tabela os usa o índice detail_id para filtrar linhas antes da execução da função de janela e elimina a maior parte dos dados antecipadamente. Essa consulta leva aproximadamente 0,5 segundo.
SELECT *
FROM (
SELECT *
FROM db_order.tb_order
WHERE create_date >= DATE_SUB(CAST('2022-12-05 15:12:05' AS datetime), INTERVAL 5 MINUTE)
AND product_type IN (2, 4)
) o
LEFT JOIN (
SELECT *
FROM db_order.tb_order_detailed
WHERE update_time >= DATE_SUB('2022-12-05 15:12:05', INTERVAL 50 MINUTE)
) od
ON o.order_id = od.order_id
LEFT JOIN LATERAL((
SELECT t.*, row_number() OVER (PARTITION BY detail_id ORDER BY update_date DESC) AS rn
FROM db_order.tb_order_sku t
WHERE update_date >= DATE_SUB('2022-12-05 15:12:05', INTERVAL 50 MINUTE)
AND coalesce(product_type, '0') <> '5'
AND od.id = detail_id
)) os;
A mudança principal é a inclusão de AND od.id = detail_id dentro da subconsulta os, combinada com a sintaxe LEFT JOIN LATERAL. Isso permite que o otimizador aplique o filtro baseado em índice antes de materializar os, em vez de depois.
Caso sua consulta não se beneficie do pushdown mesmo atendendo aos critérios gerais, confirme se a coluna de junção na tabela derivada está indexada e se a condição de junção apresenta alta seletividade.