Pular para o conteúdo

Por que o PostgreSQL é Lento para Analytics (e Como Resolver)

Resumo rápido

  • O ClickHouse é um banco colunar open source (licença Apache 2.0), criado dentro do Yandex e aberto ao público em 2016; desde 2021 é mantido pela ClickHouse Inc., empresa independente.
  • Ele está em produção em empresas como Cloudflare, que processa mais de 1 milhão de consultas de DNS por segundo com ele, além de Uber e Spotify.
  • Ele não substitui o PostgreSQL: são bancos com propósitos diferentes, um pensado para transações (OLTP) e outro para agregações em bilhões de linhas (OLAP).

Você construiu sua API em Go, conectou ao PostgreSQL e tudo funciona perfeitamente. Os usuários se cadastram, compram produtos e o sistema voa.

Mas aí o seu chefe pede um dashboard de analytics. Ele quer saber: “qual a média de vendas por hora nos últimos 5 anos, filtrado por região?”.

Você escreve a query SQL, roda, e espera… espera… 10 segundos… 30 segundos… O banco trava. A CPU vai a 100%.

O que aconteceu? O seu PostgreSQL quebrou? Não. Você apenas tentou usar um martelo para apertar um parafuso.

Bem-vindo ao mundo do ClickHouse e do armazenamento colunar. Neste tutorial você vai entender por que esse tipo de banco existe e como usá-lo, na prática, para tirar peso de relatórios pesados de cima do seu banco transacional.

O problema: linhas vs. colunas (OLTP vs. OLAP)

Para entender o ClickHouse, primeiro precisa entender por que o PostgreSQL (e MySQL, SQL Server) fica lento em relatórios pesados.

O PostgreSQL é um banco OLTP (Online Transaction Processing), orientado a linhas. Pense numa planilha: quando o Postgres grava os dados do usuário “Thiago”, ele grava a linha inteira junta (ID, nome, email, idade, endereço).

  • Vantagem: é rápido para encontrar uma pessoa específica, tipo SELECT * FROM users WHERE id = 1.
  • Desvantagem: para somar a idade de todos os usuários, o banco precisa ler a linha inteira de cada um, carregando dados inúteis (como o endereço) só para chegar na idade. É desperdício de I/O.

O ClickHouse é um banco OLAP (Online Analytical Processing), orientado a colunas. Ele grava todos os “nomes” juntos num arquivo, todas as “idades” em outro, e assim por diante.

  • Vantagem: para somar as idades, ele lê direto o arquivo de idades e ignora o resto.
  • Resultado prático: consultas de agregação que levam segundos ou minutos no Postgres tendem a rodar em milissegundos no ClickHouse, porque ele lê só a coluna que a query realmente precisa.

Se quiser entender melhor quando o Postgres é a escolha certa antes de sair trocando de banco, vale ler o guia sobre por que o PostgreSQL é o banco de dados perfeito para a maioria dos casos.

O que é o ClickHouse

O ClickHouse nasceu dentro do Yandex, em 2009, para resolver um problema real de analytics interno (o Yandex Metrica). Em 2016, a empresa abriu o código sob licença Apache 2.0. Em 2021, o projeto virou uma empresa independente, a ClickHouse Inc., que hoje mantém o banco e vende uma versão gerenciada em nuvem.

Ele não serve para ser o banco principal da sua aplicação, onde você guarda o perfil do usuário. Ele serve para ser o motor dos seus relatórios, logs e métricas.

Hoje ele está em produção em empresas com volume gigantesco de dados: a Cloudflare documentou publicamente como usa ClickHouse para analisar mais de 1 milhão de consultas de DNS por segundo, e o próprio ClickHouse lista Uber e Spotify entre os usuários de produção em escala.

As três características que fazem a diferença

  • Armazenamento colunar: como explicado acima, dados da mesma coluna ficam fisicamente juntos no disco.
  • Compressão agressiva: como valores parecidos ficam próximos (por exemplo, uma coluna cheia de datas semelhantes), a compressão funciona muito bem. É comum ver dados que ocupam 1TB no Postgres caberem numa fração disso no ClickHouse, dependendo do tipo de dado e da configuração de compressão.
  • Processamento vetorizado: o ClickHouse usa instruções modernas da CPU (SIMD) para processar blocos de dados de uma vez, em vez de linha por linha.

Tutorial: subindo o ClickHouse em poucos minutos

Vamos subir uma instância e ver a diferença de performance na prática. A forma mais simples é via Docker.

1. Instalação com Docker

docker run -d --name clickhouse-server --ulimit nofile=262144:262144 -p 8123:8123 -p 9000:9000 clickhouse/clickhouse-server

Agora, entre no cliente do banco:

docker exec -it clickhouse-server clickhouse-client

2. Criando uma tabela com a engine MergeTree

No Postgres, você só faz CREATE TABLE. No ClickHouse, você precisa escolher a engine de armazenamento. A mais usada é a MergeTree.

CREATE TABLE acessos_site (
    id UInt64,
    url String,
    usuario_id UInt32,
    data_acesso DateTime
) ENGINE = MergeTree()
ORDER BY (data_acesso, url);

O ORDER BY aqui não serve só para ordenar a saída: é ele que define como o ClickHouse constrói o índice primário esparso. Na MergeTree, essa cláusula é obrigatória.

3. Inserindo dados em lote

O ClickHouse funciona melhor com inserções em lote. Evite fazer INSERT INTO linha por linha; insira milhares (ou milhões) de uma vez. O exemplo abaixo usa a função geradora numbers() para criar 1 milhão de linhas de teste instantaneamente:

INSERT INTO acessos_site
SELECT
    number,
    concat('https://visaobinaria.com.br/post/', toString(rand() % 100)),
    rand() % 1000,
    now() - rand() % 10000
FROM numbers(1000000);

4. Testando a performance

Agora faça uma pergunta de agregação real: “quais são as 5 URLs mais acessadas?”

SELECT
    url,
    count() as total
FROM acessos_site
GROUP BY url
ORDER BY total DESC
LIMIT 5;

Mesmo com 1 milhão de linhas, o resultado volta em poucos milissegundos, sem índice extra nenhum, porque o ClickHouse só precisa ler a coluna url. O tempo exato varia conforme o hardware, mas a ordem de grandeza (milissegundos versus segundos num banco de linhas com volume equivalente) é consistente com os benchmarks públicos de ClickHouse vs. PostgreSQL, que descrevem ganhos de 100x a 1000x em consultas analíticas típicas.

Conectando o ClickHouse a uma aplicação Go

Você não vai usar o terminal para sempre. Dá para conectar sua API Go ao ClickHouse com o driver oficial:

go get github.com/ClickHouse/clickhouse-go/v2
package main

import (
    "context"
    "fmt"
    "github.com/ClickHouse/clickhouse-go/v2"
)

func main() {
    conn, err := clickhouse.Open(&clickhouse.Options{
        Addr: []string{"127.0.0.1:9000"},
        Auth: clickhouse.Auth{
            Database: "default",
            Username: "default",
            Password: "",
        },
    })

    if err != nil {
        panic(err)
    }

    // Exemplo: lendo dados
    rows, err := conn.Query(context.Background(), "SELECT count() FROM acessos_site")
    if err != nil {
        panic(err)
    }

    for rows.Next() {
        var count uint64
        rows.Scan(&count)
        fmt.Printf("Total de linhas: %d\n", count)
    }
}

Quando não usar o ClickHouse

Não jogue seu PostgreSQL fora. O ClickHouse é ruim para:

  • Updates e deletes unitários: ele não foi feito para você mudar o email de um usuário específico. No ClickHouse, updates são operações pesadas e assíncronas (mutations), bem diferentes de um UPDATE comum de banco transacional.
  • Transações complexas com garantias ACID rígidas: não tente construir um sistema bancário de transferência de dinheiro nele. Use Postgres para isso.
  • Buscas por chave única: SELECT * FROM tabela WHERE id = 123 costuma ser mais rápido num banco orientado a linhas, como o Postgres.

Se você ainda está decidindo entre bancos relacionais e não relacionais antes mesmo de chegar nesse estágio de analytics, o guia SQL ou NoSQL: a escolha do banco de dados sem dor de cabeça ajuda a entender o ponto de partida.

E se o assunto é performance bruta em outra camada da stack (não banco de dados, mas execução de código), vale ver como o scriptc da Vercel compila TypeScript direto para binário nativo: é outro exemplo de como cortar uma camada de abstração (nesse caso, o runtime) muda a ordem de grandeza da performance, o mesmo princípio por trás do ganho do ClickHouse ao cortar a leitura de colunas desnecessárias.

Perguntas frequentes

O ClickHouse substitui o PostgreSQL? Não. Eles são complementares. O PostgreSQL é ideal para transações (OLTP) e para o estado atual da aplicação. O ClickHouse é especializado em análises (OLAP) sobre grandes volumes de dados. A arquitetura mais comum usa os dois juntos: Postgres para o que muda, ClickHouse para o histórico.

O ClickHouse é gratuito? Sim, o núcleo do ClickHouse é open source sob licença Apache 2.0 e pode ser instalado gratuitamente nos seus próprios servidores. Existe também uma versão gerenciada em nuvem, a ClickHouse Cloud, que é paga.

Por que o ClickHouse é tão rápido para analytics? Principalmente por três fatores: armazenamento orientado a colunas (lê só os dados necessários para a query), compressão eficiente de dados semelhantes, e execução vetorizada (processa vários valores de uma vez usando instruções SIMD da CPU).

Quem usa ClickHouse em produção hoje? Empresas com volume grande de eventos e logs, como Cloudflare (analytics de DNS), Uber e Spotify, entre outras listadas na própria documentação oficial do projeto.

Conclusão

A arquitetura moderna de dados costuma envolver dois bancos, não um só:

  • PostgreSQL (OLTP): para o estado atual da aplicação, como usuários, pedidos e pagamentos.
  • ClickHouse (OLAP): para o histórico de eventos, como logs, cliques e telemetria.

Ao adicionar o ClickHouse ao seu cinto de utilidades, você deixa de temer tabelas com bilhões de linhas e passa a tratar dado histórico como um ativo, não como um problema de performance.

Recomendação relacionada

Dominando o PostgreSQL

Um guia em português pra quem quer ir além do básico de bancos de dados relacionais.

Ver na Amazon →

Como Associado Amazon, Visão Binária pode ganhar uma comissão sobre compras qualificadas feitas através deste link, sem custo adicional pra você.