Saiba como ajustar consultas em tabelas internas do Hologres mantendo estatísticas atualizadas, configurando shards, otimizando junções e agregações e projetando esquemas de tabela eficientes.
Guia rápido de decisão
|
Sintoma |
Causa provável |
Ação recomendada |
|
Junções lentas em tabelas internas grandes |
Estatísticas desatualizadas |
Execute ANALYZE em todas as tabelas envolvidas na junção |
|
Consultas verificam muitas linhas para filtros de intervalo ou igualdade |
Ausência de clustering key, bitmap columns ou segment key |
Adicione uma clustering_key para filtros de intervalo, bitmap_columns para filtros de igualdade ou uma segment_key para intervalos baseados em tempo |
|
Alta latência em consultas pontuais |
Tipo de armazenamento inadequado ou ausência de chave primária/índice |
Use armazenamento híbrido ou por linha e defina uma chave primária e um índice apropriados |
|
Agregações COUNT DISTINCT lentas |
Deduplicação exata com alto consumo de recursos |
Use APPROX_COUNT_DISTINCT ou UNIQ e considere usar a chave distinta como chave de distribuição |
|
Agregações GROUP BY lentas |
Redistribuição de dados e skew de dados nas chaves do GROUP BY |
Defina as chaves do GROUP BY como chaves de distribuição sempre que possível e corrija o skew de dados |
Mantenha as estatísticas
As Estatísticas (por exemplo, distribuições de dados, linhas, colunas) ajudam o otimizador a escolher planos de execução eficientes. Estatísticas desatualizadas podem causar seleção inadequada da ordem de junção e erros OOM.
Verifique se as estatísticas estão atualizadas
Execute EXPLAIN na consulta e verifique a estimativa de rows para cada tabela.
Se uma tabela grande mostrar rows=1000 (o valor padrão), as estatísticas estão desatualizadas.
Atualize as estatísticas
Execute ANALYZE nas tabelas com estatísticas obsoletas:
analyze <tablename>;
Identifique quando atualizar as estatísticas
Execute analyze <tablename> nas seguintes situações:
Após importar dados.
Após múltiplas operações INSERT, UPDATE ou DELETE.
Para tabelas internas e externas.
Nas tabelas pai de tabelas particionadas.
Caso encontre erros OOM durante junções ou consultas lentas, execute analyze <tablename> antes de importar os dados.
Configure a contagem de shards
A contagem de shards determina o paralelismo das consultas. Poucos shards limitam o paralelismo; muitos aumentam a sobrecarga de inicialização.
Entenda a contagem padrão de shards
O Hologres define uma contagem padrão de shards com base nas especificações da instância, aproximadamente igual às CUs de consulta disponíveis. Após o dimensionamento, os bancos de dados existentes mantêm sua contagem original de shards — apenas novos bancos de dados usam o padrão atualizado.
Determine quando ajustar a contagem de shards
Após aumentar a capacidade em 5 vezes ou mais: crie um novo Table Group com uma contagem maior de shards.
Para novas cargas de trabalho de negócios: crie um novo Table Group com a contagem adequada de shards.
Ao enfrentar problemas de paralelismo: verifique se o total de shards excede o padrão recomendado.
O total de shards em todos os Table Groups não deve exceder a contagem padrão de shards da instância para garantir a utilização ideal da CPU.
Otimize consultas JOIN
Utilize os métodos a seguir para melhorar o desempenho de junções.
Atualize estatísticas para consultas de junção
Conforme mencionado em Manter estatísticas, estatísticas desatualizadas podem fazer com que a tabela maior crie uma tabela hash, reduzindo a eficiência da junção. Execute ANALYZE para atualizar as estatísticas da tabela.
Selecione chaves de distribuição para junções locais
As chaves de distribuição determinam como os dados são distribuídos entre os shards. Uma seleção adequada permite junções locais e reduz a movimentação de dados.
Princípios para selecionar chaves de distribuição:
Use as colunas de junção como chave de distribuição.
Prefira colunas presentes em cláusulas GROUP BY frequentes.
Escolha colunas com distribuição de dados uniforme e discreta.
Exemplo: Ao unir tabelas frequentemente por uma coluna específica, defina essa coluna como chave de distribuição para ambas as tabelas:
-- Create tables with matching distribution keys
BEGIN;
CREATE TABLE orders (order_id INT, customer_id INT, amount DECIMAL);
CALL set_table_property('orders', 'distribution_key', 'customer_id');
COMMIT;
BEGIN;
CREATE TABLE customers (id INT, name TEXT);
CALL set_table_property('customers', 'distribution_key', 'id');
COMMIT;
Com as chaves de distribuição corretas, o plano de execução não mostra o operador Redistribute Motion, confirmando que as junções são locais.
Use Runtime Filter em junções
A partir da V2.0, o Hologres aplica automaticamente Acelerar junções de várias tabelas com runtime filters para junções entre tabelas grandes e pequenas, reduzindo os dados verificados sem necessidade de configuração manual.
Ajuste algoritmos de ordem de junção
Em consultas que unem muitas tabelas, o otimizador pode levar muito tempo para encontrar a ordem ideal de junção. Ajuste o algoritmo conforme necessário:
set optimizer_join_order = '<value>';
|
Algoritmo |
Caso de uso |
Compromisso |
|
exhaustive2 |
Padrão para a maioria das consultas |
Melhor plano, maior custo de otimização |
|
greedy |
Mais de 10 tabelas |
Otimização mais rápida, plano potencialmente subótimo |
|
query |
SQL simples e bem ordenado |
Executa na ordem do SQL, menor custo de otimização |
Otimize operadores Motion em junções
O Hologres usa operadores Motion para redistribuir dados entre shards:
|
Tipo de Motion |
Descrição |
|
Redistribute Motion |
Reorganiza os dados por hash ou aleatoriamente. |
|
Broadcast Motion |
Copia os dados para todos os shards. |
|
Gather Motion |
Coleta dados em um único shard. |
|
Forward Motion |
Transfere dados entre fontes externas e o Hologres para consultas federadas. |
Verifique nos planos de execução se há operadores Motion custosos e ajuste o design da tabela:
Operadores Motion demorados: redesenhe a distribuição.
Operadores Motion ineficientes causados por estatísticas desatualizadas: atualize as estatísticas com
analyze.Broadcasting de tabelas pequenas: reduza a contagem de shards para otimizar a eficiência do Broadcast Motion.
Otimize agregações
Otimize COUNT DISTINCT
Substitua o COUNT DISTINCT exato (que consome muitos recursos) pelo APPROX_COUNT_DISTINCT (mais rápido, taxa de erro de 0,1% a 1%) quando uma pequena variação for aceitável.
Troque o COUNT DISTINCT pelo UNIQ (V1.3+).
-
Defina uma chave de distribuição adequada.
Use a chave do COUNT DISTINCT como chave de distribuição para evitar reorganização de dados entre shards.
-
Atualize para a V2.1+ para obter otimizações integradas.
A versão V2.1+ inclui otimizações nativas para cenários de COUNT DISTINCT, incluindo um ou mais COUNT DISTINCT, skew de dados e consultas sem GROUP BY.
Force a agregação em vários estágios
A agregação em vários estágios reduz a transferência de dados ao realizar agregações parciais dentro de cada shard primeiro:
set optimizer_force_multistage_agg = on;
Otimize múltiplas funções de agregação na mesma coluna
A partir da V4.0, o Hologres deduplica automaticamente funções de agregação idênticas na mesma coluna, reduzindo a computação. Atualize para a V4.0+ para usar essa otimização.
Exemplo:
-- Create a test table.
CREATE TABLE tbl(x int4, y int4);
-- Insert test data.
INSERT INTO tbl VALUES (1,2), (null,200), (1000,null), (10000,20000);
-- Query data
SELECT
sum(x + 1),
sum(x + 2),
sum(x - 3),
sum(x - 4)
FROM
tbl;
O plano de consulta mostra que x é a única chave de agrupamento.
Para desativar:
-- Disable at the session level.
SET hg_experimental_remove_related_group_by_key = off;
-- Disable at the DB level.
ALTER DATABASE <database_name> SET hg_experimental_remove_related_group_by_key = off;
Otimize o esquema da tabela e os índices
Escolha formatos de armazenamento
O Hologres suporta armazenamento por linha, por coluna e híbrido. Escolha com base na sua carga de trabalho:
|
Formato de armazenamento |
Ideal para |
Compromisso |
|
Armazenamento por linha |
Consultas pontuais por chave primária, UPDATE/DELETE frequentes |
Baixo desempenho em varreduras de intervalo e agregações |
|
Armazenamento por coluna |
Análises, consultas multicoluna, agregações |
UPDATE/DELETE e consultas pontuais mais lentos |
|
Armazenamento híbrido linha-coluna |
Cargas de trabalho mistas |
Maior sobrecarga de armazenamento |
Escolha tipos de dados
Prefira tipos menores sempre que possível (
INTem vez deBIGINT).Especifique a precisão para tipos
DECIMAL/NUMERIC.Evite
FLOATouDOUBLEem colunas deGROUP BY.Use
TEXTpara maior versatilidade. Minimize N ao usarVARCHAR(N)ouCHAR(N).Prefira
TIMESTAMPTZeDATEem vez deTEXTpara datas.Mantenha tipos de dados consistentes nas condições de junção para evitar conversões implícitas.
Projete uma chave primária
As chaves primárias garantem a unicidade dos dados. Selecione um método de deduplicação durante a importação:
ignore: Ignora os novos dados.
update: Sobrescreve os dados antigos.
Chaves primárias adequadas melhoram os planos de execução, especialmente para consultas GROUP BY.
No modo de armazenamento colunar, as chaves primárias tornam as gravações mais lentas — o throughput geralmente é 3 vezes maior sem elas.
Use uma tabela particionada
O Hologres suporta particionamento de nível único. Um particionamento adequado acelera as consultas, mas partições em excesso criam arquivos pequenos e prejudicam o desempenho.
Crie partições diárias para dados incrementais a fim de isolar o armazenamento e o acesso.
Cenários aplicáveis:
Use DROP ou TRUNCATE em partições inteiras para obter melhor desempenho do que DELETE e sem impacto em outras partições.
Isole varreduras em partições específicas ou tabelas filhas.
Utilize tabelas particionadas para importações periódicas em tempo real. Por exemplo, use a data como chave de partição. Instruções de exemplo:
begin;
create table insert_partition(c1 bigint not null, c2 boolean, c3 float not null, c4 text, c5 timestamptz not null) partition by list(c4);
call set_table_property('insert_partition', 'orientation', 'column');
commit;
create table insert_partition_child1 partition of insert_partition for values in('20190707');
create table insert_partition_child2 partition of insert_partition for values in('20190708');
create table insert_partition_child3 partition of insert_partition for values in('20190709');
select * from insert_partition where c4 >= '20190708';
select * from insert_partition_child3;
Escolha índices adequados
O Hologres oferece vários tipos de índice. Defina os índices ao criar a tabela:
|
Tipo |
Finalidade |
Consulta de exemplo |
|
clustering_key |
Consultas de intervalo e filtragem |
|
|
bitmap_columns |
Consultas de igualdade |
|
|
segment_key (também conhecida como event_time_column) |
Filtragem baseada em tempo (nível de arquivo) Filtragem rápida no nível de arquivo antes dos índices bitmap ou clustering. Segue a correspondência de prefixo mais à esquerda (geralmente 1 coluna). Use o primeiro timestamp não vazio como segment_key. |
|
Observações:
As chaves de clustering e segment seguem o princípio de correspondência de prefixo mais à esquerda.
Os índices bitmap suportam consultas AND/OR em várias colunas.
Use
segment_keypara filtragem baseada em tempo primeiro, depoisbitmap_columnspara igualdade ouclustering_keypara consultas de intervalo.
Exemplo:
BEGIN;
CREATE TABLE events (
event_id INT NOT NULL,
user_id INT NOT NULL,
event_time TIMESTAMPTZ NOT NULL,
event_type TEXT
);
CALL set_table_property('events', 'clustering_key', 'event_time');
CALL set_table_property('events', 'segment_key', 'event_time');
CALL set_table_property('events', 'bitmap_columns', 'user_id,event_type');
COMMIT;
É possível adicionar bitmap_columns após a criação da tabela. Já clustering_key e segment_key devem ser especificadas na criação.
Verifique o uso do índice em uma consulta executando EXPLAIN:
EXPLAIN SELECT * FROM events WHERE event_time > '2026-01-01';
Desative a codificação de dicionário para colunas de caracteres
A codificação de dicionário acelera comparações de strings, mas adiciona sobrecarga de codificação/decodificação. Desative-a para colunas onde o custo de comparação é baixo:
BEGIN;
CREATE TABLE logs (id INT, message TEXT);
CALL set_table_property('logs', 'dictionary_encoding_columns', '');
COMMIT;
Otimize instruções SQL
Evite SQL externo (Postgres), como NOT IN
O Hologres usa o HQE (Hologres Query Engine) para obter o melhor desempenho. Operadores não suportados recorrem ao PQE (Postgres Query Engine), que é mais lento.
Verifique o fallback para PQE nos planos de execução:
EXPLAIN SELECT * FROM orders WHERE id NOT IN (SELECT id FROM cancelled_orders);
Se você vir External SQL (Postgres), reescreva a consulta:
|
Não suportado pelo HQE |
Rreescrever para |
Exemplo |
Observações |
|
|
|
|
N/A. |
|
|
|
|
regexp_split_to_table suporta expressões regulares. A partir do Hologres V2.0.4, o HQE suporta |
|
|
|
Reescreva como:
|
Algumas versões V0.10 e anteriores não suportam substring. A partir da V1.3, o HQE suporta entrada sem regex para substring. |
|
|
|
Reescreva como:
|
|
|
|
Remova |
Reescreva como:
|
N/A. |
|
|
|
Reescreva como:
|
Suportado pelo HQE a partir do Hologres V2.0. |
|
|
|
Reescreva como:
|
Suportado pelo HQE a partir do Hologres V2.0. |
Evite consultas LIKE difusas
Evite buscas difusas como a operação LIKE, pois elas não utilizam índices.
Otimize consultas ORDER BY LIMIT**
A partir da V1.3, o Hologres suporta Merge Sort para consultas ORDER BY ... LIMIT, eliminando operações de classificação redundantes.
Otimize consultas GROUP BY
Defina a coluna do GROUP BY como chave de distribuição para reduzir a redistribuição de dados.
-- If data is distributed based on the values in column a, runtime data redistribution is reduced, and the parallel computing capability of shards is fully utilized.
select a, count(1) from t1 group by a;
A partir da V4.0, o Hologres reescreve automaticamente colunas relacionadas do GROUP BY para reduzir mesclagens (profundidade máxima de busca: 5 camadas). Uma cláusula como GROUP BY COL_A, ((COL_A + 1)), ((COL_A + 2)) é reescrita para GROUP BY COL_A. Exemplo:
CREATE TABLE tbl (
a int,
b int,
c int
);
-- Query
SELECT
a,
a + 1 as a1,
a + 2 as a2,
sum(b)
FROM tbl
GROUP BY
a,
a1,
a2;
O plano de execução confirma a reescrita — a cláusula GROUP BY contém apenas a coluna a.
QUERY PLAN
Gather (cost=0.00..5.00 rows=1 width=20)
-> Project (cost=0.00..5.00 rows=1 width=20)
-> HashAggregate (cost=0.00..5.00 rows=1 width=12)
Group Key: a
-> Redistribution (cost=0.00..5.00 rows=1 width=8)
Hash Key: a
-> Local Gather (cost=0.00..5.00 rows=1 width=8)
-> Seq Scan on tbl (cost=0.00..5.00 rows=1 width=8)
Query Queue: init_warehouse.default_queue
Optimizer: HQO version 4.0.0
Para desativar:
-- Disable the feature at the session level.
SET hg_experimental_remove_related_group_by_key = off;
-- Disable the feature at the database level.
ALTER DATABASE <database_name> SET hg_experimental_remove_related_group_by_key = off;
Ative a reutilização de CTE
Quando uma CTE é referenciada várias vezes, ative a reutilização de CTE para evitar recálculos (V1.3+):
SET optimizer_cte_inlining=off;
A reutilização de CTE vem desativada por padrão. Ative-a manualmente via GUC.
A reutilização de CTE depende do Spill no estágio Shuffle. Grandes volumes de dados podem afetar o desempenho devido a taxas de consumo variáveis.
Otimize a análise Top-N
-
Em cenários OLAP, recuperar os N principais registros dentro de um grupo é um requisito comum. Por exemplo, a seguinte consulta SQL recupera os dois principais registros da tabela
tdentro de cada partiçãob, classificados pora:CREATE TABLE t ( a int, b int ); INSERT INTO t VALUES (2, 1), (3, 1), (4, 1), (5, 2), (6, 2); SELECT * FROM ( SELECT a, b, row_number() OVER (PARTITION BY b ORDER BY a) AS rn FROM t) t1 WHERE rn <= 2;O resultado da execução é o seguinte:
a b rn 5 2 1 6 2 2 2 1 1 3 1 2 -
A partir do Hologres V4.1, o operador
Partition Sortempurra a cláusulaLIMITpara dentro daPartition, filtrando dados antecipadamente durante a classificação. Isso reduz a memória necessária para funções de janela comorow_numbererankem cenários Top-N, diminuindo o risco de OOM. Ativado por padrão. Para desativar:-- Disable the feature at the session level. SET hg_experimental_enable_hash_partitioned_sort_v2 = off; -- Disable the feature at the database level. ALTER DATABASE <database_name> SET hg_experimental_enable_hash_partitioned_sort_v2 = off;
Lide com skew de dados
A distribuição desigual de dados torna as consultas lentas. Verifique a contagem de linhas por shard para detectar skew:
-- hg_shard_id is a built-in hidden column in each table that describes the shard where the corresponding row of data is located.
SELECT hg_shard_id, count(1) FROM t1 GROUP BY hg_shard_id;
Se alguns shards tiverem significativamente mais linhas do que outros:
-
Altere a
distribution_keypara uma coluna com distribuição de dados uniforme.ImportanteAlterar a chave de distribuição exige recriar a tabela e reimportar os dados.
Se os dados forem inerentemente enviesados, otimize sob a perspectiva de negócios.
Desative o cache de resultados para testes
O Hologres armazena resultados de consultas em cache por padrão. Desative o cache ao avaliar o desempenho:
set hg_experimental_enable_result_cache = off;