Introdução ao ClickHouse
O ClickHouse é um sistema de gerenciamento de banco de dados (DBMS) columnar distribuído, projetado especificamente para processamento analítico online (OLAP). Desenvolvido inicialmente pela Yandex, ele se destaca pela capacidade de processar grandes volumes de dados com latência extremamente baixa, superando muitas soluções MPP comerciais em benchmarks de velocidade.
Sua arquitetura permite escalabilidade linear e alta confiabilidade, sendo ideal para cenários onde a maioria das operações são leituras intensivas e os dados são inseridos em grandes lotes. Embora não suporte transações tradicionais ou atualizações frequentes de linhas únicas, sua performance em consultas agregadas sobre bilhões de registros é excepcional.
Instalação e Configuração do Servidor
Para implantar uma instância standalone, é necessário preparar o ambiente operacional. O ClickHouse fornece pacotes RPM que podem ser obtidos diretamente dos repositórios oficiais. É crucial garantir que todos os pacotes instalados pertençam à mesma versão para evitar incompatibilidades.
Pré-requisitos de Hardware e Sistema
Antes da instalação, valide se a CPU do servidor suporta o conjunto de instruções SSE 4.2, necessário para a execução vetorial das consultas:
grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 habilitado" || echo "SSE 4.2 não suportado"
Configurar o nome do host corretamente é essencial, especialmente em ambientes clusterizados. Adicione o FQDN ao arquivo /etc/hosts para garantir resolução de nomes na rede local.
Instalação dos Pacotes
Utilize o gerenciador de pacotes para instalar os arquivos RPM baixados. O comando abaixo resolve dependências automaticamente:
yum localinstall *.rpm
Após a instalação, a estrutura de diretórios padrão inclui:
/etc/clickhouse-server/: Contém arquivos de configuração comoconfig.xmleusers.xml./var/lib/clickhouse/: Diretório padrão para armazenamento dos dados./var/log/clickhouse-server/: Local onde os logs do sistema são persistidos.
Configuração de Armazenamento e Serviço
Recomneda-se alterar o diretório de dados padrão se houver partições específicas montadas para maior capacidade. Edite o arquivo config.xml para definir novos caminhos:
<path>/opt/clickhouse_data/</path>
<tmp_path>/opt/clickhouse_data/tmp/</tmp_path>
<user_files_path>/opt/clickhouse_data/user_files/</user_files_path>
Certifique-se de que o usuário clickhouse tenha propriedade sobre esses diretórios:
chown clickhouse:clickhouse /opt/clickhouse_data/ -R
Para iniciar o serviço, utilize o systemd ou o utilitário nativo:
systemctl start clickhouse-server
# Ou
clickhouse start
Verifique se o serviço está escutando na porta nativa 9000:
netstat -nltp | grep 9000
Gerenciamento de Acesso e Portas
O ClickHouse expõe principalmente duas portas para comunicação:
- 9000 (TCP): Utilizada pelo cliente nativo
clickhouse-clientpara consultas interativas. - 8123 (HTTP): Utilizada para conexões via JDBC, interfaces web e ferramentas de visualização.
Para permitir conexões remotas, é necessário ajustar o firewall e a configuração de escuta. Libere as portas no firewall:
firewall-cmd --add-port=9000/tcp --permanent
firewall-cmd --add-port=8123/tcp --permanent
firewall-cmd --reload
No arquivo config.xml, altere a configuração de listen_host para aceitar conexões de qualquer interface de rede:
<listen_host>::</listen_host>
Reinicie o serviço para aplicar as mudanças. Para segurança, configure senhas para os usuários editando users.xml. Gere um hash SHA256 da senha desejada e insira na tag <password_sha256_hex> correspondente ao usuário.
Operações de Importação e Exportação
O ClickHouse otimiza a ingestão de dados quando realizada em lotes grandes. Evite inserções linha por linha. O formato TSV (Tab Separated Values) é frequentemente utilizado para imports rápidos via linha de comando.
Preparação do Esquema
Crie um banco de dados e defina tabelas adequadas para o volume de dados. Abaixo, um exemplo de tabela para logs de navegação web:
CREATE TABLE analise.web_logs
(
`id_sessao` UInt64,
`navegador Habilitado` UInt8,
`titulo_pagina` String,
`timestamp_evento` DateTime,
`data_evento` Date,
`id_counter` UInt32,
`ip_cliente` UInt32,
`id_usuario` UInt64,
`url_origem` String,
`pais_regiao` UInt32
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(data_evento)
ORDER BY (id_counter, data_evento, intHash32(id_usuario))
SETTINGS index_granularity = 8192;
Ingestão de Dados
Utilize o cliente CLI para importar arquivos compactados ou planos. O parâmetro max_insert_block_size controla o tamanho do lote:
clickhouse-client --query "INSERT INTO analise.web_logs FORMAT TSV" --max_insert_block_size=100000 < logs_navegacao.tsv
Para exportação, utilize consultas SELECT formatadas para CSV ou TSV, redirecionando a saída para um arquivo:
clickhouse-client --query="SELECT * FROM analise.web_logs FORMAT CSV" > /backup/export_logs.csv
Engines de Tabela MergeTree
A família de engines MergeTree é o núcleo do armazenamento no ClickHouse. Ela oferece recursos como armazenamento columnar, particionamento, índices primários esparsos e ordenação de dados.
Estrutura e Indexação
Ao criar uma tabela MergeTree, é definido um chave primária e uma chave de ordenação. A chave primária não exige unicidade; ela serve para construir o índice esparso. Por padrão, o índice é criado a cada 8192 linhas (index_granularity), o que mantém o índice residente na memória RAM para acesso rápido.
Exemplo de criação de tabela simples:
CREATE TABLE cadastro.clientes
(
cod_cliente UInt32,
nome_completo String,
data_nascimento Date,
cidade_origem String
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(data_nascimento)
PRIMARY KEY cod_cliente
ORDER BY (cod_cliente, data_nascimento);
Dados inseridos em momentos diferentes são armazenados em partes separadas ("parts"). Para forçar a consolidação dessas partes em um único conjunto, execute:
OPTIMIZE TABLE cadastro.clientes FINAL;
O comando FINAL garante que todas as partes sejam mescladas imediatamente, embora isso possa ser intensivo em recursos.
Particionamento
O particionamento permite isolar dados logicamente, facilitando a exclusão de blocos antigos ou consultas restritas. Ao especificar PARTITION BY, o ClickHouse cria diretórios distintos para cada partição no sistema de arquivos.
Engine ReplacingMergeTree
Uma variação comum é a ReplacingMergeTree, projetada para eliminar duplicatas durante o processo de merge em segundo plano. É importante notar que a deduplicação não é imediata na inserção, ocorrendo apenas quando as partes de dados são combinadas.
Deduplicação Simples
Se nenhuma coluna de versão for especificada, o engine mantém a última linha encontrada durante a merge para chaves idênticas definidas em ORDER BY.
CREATE TABLE registros.atualizacoes
(
id_registro UInt32,
descricao String,
regiao String,
data_atualizacao Date
)
ENGINE = ReplacingMergeTree()
PARTITION BY regiao
PRIMARY KEY id_registro
ORDER BY (id_registro, descricao);
Controle de Versão
Para garantir que a lógica de substituição siga uma regra de negócio específica (como manter o registro com maior número de versão), defina uma coluna de versão no engine. Isso evita que inserções fora de ordem sobrescrevam dados mais recentes erroneamente.
CREATE TABLE registros.metricas_versions
(
id_metrica UInt32,
valor_atual Float64,
regiao String,
versao_registro UInt32
)
ENGINE = ReplacingMergeTree(versao_registro)
PARTITION BY regiao
PRIMARY KEY id_metrica
ORDER BY (id_metrica, valor_atual);
Ao inserir dados, incremente a versão. Durante a otimização, o ClickHouse preservará automaticamente a linha com o maior valor na coluna versao_registro para cada chave primária dentro da partição.
INSERT INTO registros.metricas_versions VALUES (1, 10.5, 'BR', 1), (1, 12.0, 'BR', 2);
OPTIMIZE TABLE registros.metricas_versions FINAL;