DevGuideTK
← Trilha Backend

Séries temporais

Bancos otimizados para medições ao longo do tempo, com retenção e agregação.

As decisões com séries temporais são cinco: qual banco, como particionar, quanto guardar de cada resolução, como resumir e como lidar com a cardinalidade.

Qual banco

OpçãoBom paraCustos
PostgreSQL comum, com particionamento por dataVolumes moderados, quando não se quer extensãoRetenção, compressão e resumos feitos à mão
TimescaleDBMedições de negócio ao lado dos dados relacionais, com SQL completoUma extensão a instalar; nem todo PostgreSQL gerenciado a oferece
PrometheusMétricas de servidores e aplicações, com alertasNão é para dados de negócio nem para guardar por anos; consulta em PromQL
InfluxDB, QuestDBIngestão muito alta de medições, em banco dedicadoOutro banco, com linguagem e ecossistema próprios
ClickHouseSéries temporais com análises pesadas e muitas dimensõesVer o tópico de bancos colunares
Serviços gerenciados (Timestream, Azure Data Explorer, Grafana Cloud)Sem operar servidoresCusto por volume

A pergunta que separa os casos: o dado é métrica de sistema (CPU, latência, erros) ou dado de negócio (leituras de sensores de clientes, preços, consumo)? Para métricas, o ecossistema do Prometheus é o padrão. Para dados de negócio, que se cruzam com clientes e contratos, o TimescaleDB mantém tudo no mesmo banco.

Como particionar

DecisãoRecomendação
Tamanho do pedaçoQue os pedaços recentes, com os índices, caibam na memória; um dia é um começo comum
ÍndicePelas colunas que filtram junto com o tempo: (sensor_id, ts DESC)
Agrupar ao comprimirPela coluna mais filtrada (segmentby = 'sensor_id'), ordenando pelo tempo
Quando comprimirDepois que o dado para de mudar: dias ou semanas, conforme o atraso com que as medições chegam

Quanto guardar de cada resolução

A política mais comum guarda cada resolução por um tempo diferente:

ResoluçãoPor quanto tempoPara quê
Cada medição7 a 30 diasInvestigar o detalhe recente
Média por hora1 a 2 anosPainéis e comparações
Média por diaPara sempre, ou anosTendências e relatórios

Com o TimescaleDB, isso são três políticas: retenção nas medições brutas (add_retention_policy), um resumo contínuo por hora com retenção própria e outro por dia. No teste do nível Conceito, apagar 3 dias com DELETE levou 4,4 segundos e não devolveu espaço; o drop_chunks levou 115 ms e devolveu 523 MB.

Antes de apagar o bruto, confira que os resumos cobrem o período: uma vez apagado, o minuto a minuto não volta.

Como resumir

FormaAtualizaçãoCusto
Calcular na consultaSempre atualRecalcula a cada acesso: 127 ms no teste
Visão materializada comumSó quando atualizada, e recalcula tudoSimples; pesada com muito dado
Resumo contínuo (TimescaleDB)Incremental, por política7,7 ms no teste; mostra só o materializado, por padrão
Resumo contínuo com dados recentes em tempo realmaterialized_only = false: junta o resumo com o bruto ainda não materializadoUm pouco mais lento, sempre atual

Cuidado ao combinar resumos: a média das médias por hora só é a média do dia se todas as horas tiverem o mesmo número de medições. Guarde a soma e a contagem (ou a média e a contagem), e combine com sum(media * n) / sum(n), como a consulta do teste fez.

Cardinalidade

Em bancos de métricas, cada combinação de nome e rótulos é uma série separada: requisicoes{rota="/pedidos", status="200"}. O número de séries é a cardinalidade, e é ela que pesa na memória e no disco.

RótuloValores possíveisEfeito
statusUma dúziaSeguro
rota (o modelo, como /pedidos/{id})DezenasSeguro
rota (a URL real, como /pedidos/981)IlimitadosUma série por pedido: explode
usuario_id, pedido_id, request_idIlimitadosNunca como rótulo de métrica; vai para logs ou rastreamento

Resumo da decisão

  1. Prometheus para métricas de sistema; TimescaleDB (ou outro banco de séries) para medições de negócio.
  2. Particionar por tempo, com índice pela coluna que filtra junto com o tempo.
  3. Retenção por resolução: bruto por dias, resumos por anos, com drop_chunks e nunca DELETE em massa.
  4. Comprimir o que parou de mudar.
  5. Resumos contínuos com soma e contagem, e saber se mostram os dados mais recentes.
  6. Gravar em lotes, e rótulos de métricas só com poucos valores.

O próximo nível mostra a gravação em lote e a média por hora nas cinco linguagens.

Prompts para aprofundar

Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.

  • Escolher onde guardar minhas séries temporais

    Preciso guardar séries temporais no meu sistema.
    
    Pergunte o que é medido, quantas medições por segundo, por quanto tempo guardar, que consultas e painéis existem e se os dados se cruzam com outras tabelas do sistema.
    
    Compare para o meu caso PostgreSQL com particionamento, TimescaleDB, Prometheus, InfluxDB e ClickHouse. Recomende uma opção e explique a política de retenção, compressão e resumos.
  • Desenhar a retenção dos dados

    Quero definir quanto tempo guardar cada resolução das minhas séries temporais.
    
    Pergunte o que os usuários consultam, com que detalhe e de que período, e se há exigências legais ou contratuais.
    
    Monte comigo a política: o que guardar bruto e por quanto tempo, quais resumos (por hora, por dia) e por quanto tempo, quando comprimir, e como confirmar que os resumos cobrem o período antes de apagar o bruto.
  • Métricas da aplicação sem explodir a cardinalidade

    Quero instrumentar minha aplicação com métricas sem criar séries demais.
    
    Pergunte qual linguagem e qual sistema de métricas eu uso, e o que eu quero acompanhar.
    
    Me ajude a definir as métricas, os rótulos de cada uma com os valores possíveis, o que vai para logs e rastreamento em vez de métricas, e como estimar o número de séries antes de colocar em produção.