Cláusulas GROUP BY ou ORDER BY redundantes forçam o banco de dados a executar operações desnecessárias de ordenação ou hash, consumindo recursos significativos de CPU e memória. Essa sobrecarga é especialmente custosa para consultas de processamento analítico (AP) em grandes conjuntos de dados. O PolarDB for MySQL detecta e remove automaticamente essas operações redundantes por meio da análise de dependência funcional (FD), proporcionando um desempenho de consulta até 29% mais rápido nos benchmarks TPC-H, sem exigir alterações no código da aplicação.
Escopo
Série do produto: Cluster Edition, Standard Edition
Versão: MySQL 8.0.2, revisão 8.0.2.2.33 ou posterior
Ative o recurso
Dois parâmetros controlam essa otimização:
|
Parâmetro |
Nível |
Padrão |
Valores válidos |
|
|
Global/Sessão |
|
|
|
|
Global/Sessão |
|
|
Valores válidos:
REPLICA_ON(padrão): ativa o recurso apenas em nós somente leitura (RO).ON: ativa o recurso em todos os nós.OFF: desativado.
Nomenclatura dos parâmetros por interface:
Console do PolarDB: os parâmetros incluem o prefixo
loose_para garantir compatibilidade com arquivos de configuração do MySQL. Localize e modifiqueloose_groupby_elimination_modeeloose_orderby_elimination_mode.Sessão de banco de dados (com o comando
SET): remova o prefixoloose_e utilize o nome original do parâmetro —groupby_elimination_modeeorderby_elimination_mode.
Como funciona
O otimizador elimina cláusulas GROUP BY e ORDER BY redundantes ao inferir dependências funcionais (FDs) a partir dos metadados das tabelas e das condições da consulta.
O que é uma dependência funcional?
Se a coluna A determina unicamente a coluna B, então B depende funcionalmente de A — representado como A -> B. Por exemplo, em uma tabela de usuários onde user_id é a chave primária, a relação user_id -> nickname é válida, pois cada user_id corresponde a exatamente um nickname.
Fontes de dependência funcional:
|
Source |
Exemplo |
|
Chaves primárias e chaves únicas |
|
|
Condições de equi-join |
|
|
Condições de filtro constante |
|
Regras de otimização:
|
Regra |
Condição |
Resultado |
|
Eliminação de |
As colunas do |
Remoção de toda a cláusula |
|
Eliminação de |
Todas as colunas do |
Remoção do |
|
Eliminação de |
Todas as colunas do |
Remoção de toda a cláusula |
|
Simplificação de |
Existe FD entre as colunas da cláusula (ex.: |
Simplificação da cláusula (ex.: para |
Cenários de otimização
Cenário 1: Agrupamento por chave primária ou única
Condições de acionamento:
A cláusula
GROUP BYinclui a chave primária de uma tabela.As demais colunas na lista do
GROUP BYsão determinadas funcionalmente por essa chave.
Cenário de negócio: calcular a contagem total de pedidos por usuário e exibir o nome de usuário correspondente.
SQL original:
-- user_id is the primary key of the user table and uniquely determines user_name.
SELECT
u.user_id,
u.user_name,
COUNT(o.order_id)
FROM user u
JOIN orders o ON u.user_id = o.user_id
GROUP BY
u.user_id,
u.user_name;
Ação do otimizador: como user_id é a chave primária, a FD user_id -> user_name se aplica. O otimizador simplifica GROUP BY u.user_id, u.user_name para GROUP BY u.user_id, eliminando o agrupamento redundante em user_name.
SQL otimizado:
SELECT
u.user_id,
u.user_name,
COUNT(o.order_id)
FROM user u
JOIN orders o ON u.user_id = o.user_id
GROUP BY u.user_id;
Verifique a otimização:
SHOW WARNINGS;
A coluna Message exibe a consulta reescrita apenas com GROUP BY u.user_id, confirmando a remoção de u.user_name da chave de agrupamento.
Cenário 2: Agrupamento por constantes
Condições de acionamento:
Todas as colunas da cláusula
GROUP BYaparecem como constantes de igualdade na cláusulaWHERE.
Cenário de negócio: consultar uma linha específica com base em valores exatos de colunas.
SQL original:
SELECT a, b FROM t1 WHERE a = 1 AND b = 1 GROUP BY a, b;
Ação do otimizador: tanto a quanto b são constantes na cláusula WHERE, portanto o conjunto de resultados contém no máximo uma linha. O otimizador remove o GROUP BY e adiciona LIMIT 1.
SQL otimizado:
SELECT a, b FROM t1 WHERE a = 1 AND b = 1 LIMIT 1;
Verifique a otimização:
SHOW WARNINGS;
A coluna Message mostra a consulta reescrita com LIMIT 1 e sem a cláusula GROUP BY.
Cenário 3: Junção de múltiplas tabelas com agrupamento complexo (TPC-H Q10)
Condições de acionamento:
Uma junção de múltiplas tabelas propaga a FD de uma chave primária por meio de condições de equi-join.
Todas as colunas não chave na lista do
GROUP BYsão determinadas transitivamente pela chave primária.
SQL original (TPC-H Q10):
SELECT
c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment,
SUM(l_extendedprice * (1 - l_discount)) AS revenue
FROM customer, orders, lineitem, nation
WHERE c_custkey = o_custkey
AND l_orderkey = o_orderkey
AND c_nationkey = n_nationkey
-- Other filter conditions...
GROUP BY
c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment
ORDER BY revenue DESC
LIMIT 20;
Ação do otimizador:
Dependência de chave primária:
c_custkeyé a chave primária da tabelacustomer, logo determinac_name,c_acctbal,c_phone,c_address,c_commentec_nationkey.Propagação de dependência: a condição de junção
c_nationkey = n_nationkeye o fato den_nationkeyser a chave primária denationsignificam quec_custkeytambém determinan_name.Simplificação: todas as colunas não chave na lista do
GROUP BYdependem funcionalmente dec_custkey. O otimizador simplifica a cláusula paraGROUP BY c_custkey.
SQL otimizado:
SELECT
c_custkey, c_name, c_acctbal, c_phone, n_name, c_address, c_comment,
SUM(l_extendedprice * (1 - l_discount)) AS revenue
FROM customer, orders, lineitem, nation
WHERE c_custkey = o_custkey
AND l_orderkey = o_orderkey
AND c_nationkey = n_nationkey
-- Other filter conditions...
GROUP BY c_custkey
ORDER BY revenue DESC
LIMIT 20;
Verifique a otimização:
SHOW WARNINGS;
A coluna Message apresenta a consulta reescrita apenas com GROUP BY c_custkey, confirmando a remoção de todas as outras colunas da chave de agrupamento.
Cenário 4: Simplificação de ORDER BY com coluna computada
Condições de acionamento:
A cláusula
ORDER BYinclui uma coluna que é uma função determinística de outras colunas presentes na mesma cláusula.Essa coluna está definida como
UNIQUE NOT NULL.
Esquema da tabela:
CREATE TABLE t1 (
a INT,
b INT,
c INT AS (a + b) UNIQUE NOT NULL
);
SQL original:
EXPLAIN SELECT a, b FROM t1 ORDER BY a, b, c;
Ação do otimizador: a coluna c é calculada a partir de a e b (c = a + b) e definida como UNIQUE NOT NULL, estabelecendo a FD (a, b) -> c. O otimizador simplifica ORDER BY a, b, c para ORDER BY a, b.
Verifique a otimização:
SHOW WARNINGS;
+-------+------+-------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------+
| Note | 1003 | /* select#1 */ select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b` from `test`.`t1` order by `test`.`t1`.`a`,`test`.`t1`.`b` |
+-------+------+-------------------------------------------------------------------------------------------------------------------------------+
A consulta reescrita na coluna Message confirma a remoção de c da chave de ordenação.
Benchmark de desempenho
Testes realizados em um conjunto de dados padrão TPC-H de 100 GB demonstram que ativar a eliminação de GROUP BY melhora significativamente o desempenho da consulta Q10.
|
Cenário de teste |
Com eliminação |
Sem eliminação |
Melhoria |
|
In-Memory Column Index (IMCI) com 1 DOP (dentro de 1 dia da geração dos dados) |
48 segundos |
68 segundos |
29% |
|
In-Memory Column Index (IMCI) com 32 DOP (dentro de 32 dias da geração dos dados) |
1,9 segundos |
2,6 segundos |
27% |
A implementação do TPC-H descrita aqui baseia-se na metodologia de benchmarking TPC-H e não pode ser comparada aos resultados oficiais publicados do TPC-H. Estes testes não atendem integralmente a todos os requisitos do TPC-H. As melhorias reais de desempenho podem variar conforme a complexidade da consulta, a distribuição dos dados e as especificações do cluster.