Pular para o conteúdo principal
Este tutorial mostra como manter rollups pré-agregados de uma tabela de eventos de alto volume usando visões materializadas. Você criará três objetos: uma tabela de dados brutos, uma tabela de rollup e a visão materializada que grava no rollup automaticamente.

Quando usar este padrão

Use este padrão quando:
  • Você tem um fluxo de eventos somente de acréscimo (cliques, visualizações de página, IoT, logs).
  • A maioria das consultas são agregações em intervalos de tempo (por minuto/hora/dia).
  • Você quer leituras consistentes em menos de um segundo sem precisar varrer novamente todas as linhas brutas.
1

Criar a tabela de eventos brutos

Observações
  • PARTITION BY toYYYYMM(event_time) mantém as partições pequenas e fáceis de remover.
  • ORDER BY (event_time, user_id) dá suporte a consultas com intervalo de tempo definido + filtro secundário.
  • LowCardinality(String) economiza memória para dimensões categóricas.
  • TTL remove os dados brutos após 90 dias (ajuste conforme seus requisitos de retenção).
2

Defina a tabela de rollup (agregada)

Vamos fazer a pré-agregação com granularidade horária. Escolha a granularidade de acordo com a janela de análise mais comum.
Armazenamos estados de agregação (por exemplo, AggregateFunction(sum, ...)), que representam, de forma compacta, agregações parciais e podem ser combinados ou finalizados posteriormente.
3

Crie uma visão materializada que alimenta o rollup

Esta visão materializada é executada automaticamente nas inserções em events_raw e grava estados de agregação no rollup.
4

Insira alguns dados de exemplo

Insira alguns dados de exemplo:
5

Consultando o rollup

Você pode mesclar os estados no momento da leitura ou finalizá-los:

Se você espera que as leituras sempre usem o rollup, pode criar uma segunda visão materializada que grave números finalizados em uma tabela MergeTree “simples”, com a mesma granularidade de 1h. Os estados oferecem mais flexibilidade, enquanto os números finalizados tornam as leituras um pouco mais simples.
6

Filtre pelos campos da chave primária para obter o melhor desempenho

Você pode usar o comando EXPLAIN para ver como o índice é usado para descartar dados:
Query
Response
O plano de execução da consulta acima mostra três tipos de índices sendo usados: um índice MinMax, um índice de partição e um índice de chave primária. Cada índice usa campos especificados em nossa chave primária: (bucket_start, country, event_type). Para obter o melhor desempenho de filtragem, você deve garantir que suas consultas usem campos da chave primária para descartar dados.
7

Variações comuns

  • Diferentes granularidades: adicione um rollup diário:
Em seguida, uma segunda visão materializada:
  • Compressão: aplique codecs em colunas grandes (exemplo: Codec(ZSTD(3))) na tabela bruta.
  • Controle de custos: concentre a retenção mais pesada na tabela bruta e mantenha agregações de longa duração.
  • Backfilling: ao carregar dados históricos, faça a inserção em events_raw e deixe a visão materializada criar as agregações automaticamente. Para linhas existentes, use POPULATE ao criar a visão materializada, se fizer sentido, ou INSERT SELECT.
8

Limpeza e retenção

  • Aumente o TTL dos dados brutos (por exemplo, 30/90 dias), mas mantenha os roll-ups por mais tempo (por exemplo, 1 ano).
  • Você também pode usar o TTL para mover partes antigas para um armazenamento mais barato, caso o armazenamento em camadas esteja habilitado.
9

Solução de problemas

  • A visão materializada não está sendo atualizada? Verifique se as inserções vão para events_raw (não para a tabela de rollup) e se o destino da visão materializada está correto (TO events_rollup_1h).
  • Consultas lentas? Confirme se elas estão atingindo o rollup (consulte a tabela de rollup diretamente) e se os filtros de tempo estão alinhados com a granularidade do rollup.
  • Inconsistências no backfill? Use SYSTEM FLUSH LOGS e verifique system.query_log / system.parts para confirmar as inserções e os merges.
Última modificação em 19 de junho de 2026