Antes de começar
nyc_taxi.trips_small_inferred. Para executá-los conforme mostrado, crie e carregue a tabela, caso ainda não tenha feito isso:
Configurar o conjunto de dados de exemplo
Configurar o conjunto de dados de exemplo
O arquivo Parquet de origem tem aproximadamente 5,8 GB. O carregamento pode levar vários minutos, dependendo da sua rede e dos recursos disponíveis.
Escolha uma abordagem
Se as evidências não se enquadrarem em uma dessas categorias, volte ao plano de consulta em vez de forçar a consulta a se encaixar em uma abordagem.
Reduza a quantidade de dados lidos
- Use quando: A consulta lê colunas wide ou colunas desnecessárias.
- Altere: Reduza o tamanho ou o número de colunas lidas pela consulta.
- Valide: Compare
read_bytes, o uso de memória e a duração nas mesmas condições.
Revise os tipos de coluna
String, um tipo de uso geral, para esses valores e escolha o menor tipo numérico com ou sem sinal que represente com segurança o intervalo esperado. Para colunas temporais, use Date ou DateTime, a menos que precise do intervalo mais amplo ou da precisão fracionária de Date32 ou DateTime64.
Use colunas anuláveis de forma criteriosa
Uma coluna Nullable armazena uma máscara de nulos separada, além de seus valores, que o ClickHouse também precisa ler e processar. Use-a quando for importante distinguir entre um valor nulo e o valor padrão do tipo. Se uma coluna tiver a garantia de sempre conter um valor, um tipo não anulável evita esse trabalho adicional.
Antes de alterar uma coluna, verifique os dados de origem e o caminho de ingestão, em vez de presumir que dados não nulos observados sempre permanecerão não nulos. O exemplo prático de otimização demonstra como identificar colunas que contêm valores nulos e medir o efeito de alterar o esquema.
Use codificação de dicionário para valores repetidos
LowCardinality usa codificação de dicionário e costuma ser eficaz para colunas String, como valores de status, códigos de país ou outras dimensões com muito menos valores distintos do que linhas. Cerca de 10.000 valores distintos é um ponto de partida útil para identificar candidatos, não um limite fixo. Evite identificadores e outras colunas com valores predominantemente únicos e compare as medições antes e depois de alterar o tipo.
Consulte Seleção de tipos de dados para orientações mais detalhadas.
Leia apenas as colunas necessárias
SELECT *, especialmente em tabelas largas ou em consultas que retornam apenas um pequeno subconjunto de cada linha.
Use read_bytes de system.query_log para comparar a quantidade de dados lidos antes e depois de restringir as colunas selecionadas. Se read_bytes continuar alto, inspecione o plano de consulta em busca de expressões, filtros, junções ou consultas aninhadas que ainda exijam colunas adicionais.
Por exemplo, se um dashboard precisa apenas do horário de coleta, do tipo de pagamento e do valor total, selecione essas colunas em vez da linha completa:
SELECT *. O número de linhas retornadas permanece o mesmo, mas read_bytes deve refletir o conjunto menor de colunas lidas.
Alinhe o layout dos dados à consulta
- Use quando: Um filtro seletivo ainda lê muitas partes ou grânulos.
- Altere: Alinhe o layout físico aos filtros usados em consultas recorrentes.
- Valide: Compare as partes e os grânulos selecionados por
EXPLAIN indexes = 1e verifiqueread_rows,read_bytese a duração.
Comece pela chave de ordenação
MergeTree, a chave de ordenação determina como as linhas são organizadas em disco. Por padrão, ela também funciona como a chave primária que define o índice primário esparso. Diferentemente de uma chave primária em um banco de dados OLTP, a chave primária do ClickHouse não impõe unicidade. Seu ganho de desempenho vem de permitir que o ClickHouse ignore grânulos que não podem atender aos filtros de uma consulta.
Priorize as colunas que aparecem com frequência em filtros seletivos, considerando também sua ordem na chave. Agrupar valores relacionados também pode melhorar a compressão. Quando a ordem de agrupamento ou ordenação de uma consulta está alinhada à chave, o ClickHouse pode usar otimizações de processamento em ordem para GROUP BY ou ORDER BY.
Compare as partes e os grânulos selecionados por EXPLAIN indexes = 1 antes e depois de testar uma chave de ordenação diferente. Compare também read_rows, read_bytes e a duração nas mesmas condições. Consulte Como escolher uma chave primária para obter orientações detalhadas sobre a seleção.
A tabela de exemplo usa ORDER BY (); portanto, o filtro seletivo por data a seguir não tem uma chave de ordenação que possa eliminar grânulos:
No ClickHouse 25.9 e versões posteriores, essas configurações garantem que
EXPLAIN informe os índices usados e as partes e os grânulos que eles eliminam.pickup_datetime e execute o mesmo EXPLAIN nela. A seção de chave primária do plano deverá mostrar menos grânulos selecionados antes de usar medições de duração ou memória para avaliar a alteração geral.
Avalie opções adicionais de indexação e layout de dados
EXPLAIN indexes = 1 para confirmar que a consulta realmente elimina partições.
Adicione um índice de ignorar dados para um filtro localizado
Um índice de ignorar dados armazena metadados que permitem ao ClickHouse evitar a leitura de blocos que não podem corresponder a um filtro. Ele é mais útil quando a chave de ordenação não oferece suporte a um filtro importante e os valores correspondentes estão suficientemente localizados nos blocos.
Por exemplo, um índice de filtro de Bloom pode ajudar em buscas por igualdade quando a maioria dos blocos não contém o valor procurado. Use índices de ignorar dados após analisar os tipos de dados e a chave de ordenação. Um índice que raramente exclui um bloco adiciona sobrecarga de armazenamento e avaliação sem reduzir significativamente o trabalho. Teste o tipo de índice e a granularidade com dados representativos e, em seguida, use EXPLAIN indexes = 1 para comparar os grânulos selecionados e verificar read_rows, read_bytes e a duração.
Use projeções seletivamente
Projeções armazenam layouts de dados alternativos junto à tabela. Elas podem fornecer outra chave de ordenação ou um resultado pré-calculado, e o ClickHouse pode selecionar uma projeção aplicável sem exigir que a consulta faça referência a ela diretamente.
Por exemplo, uma projeção ordenada por payment_type pode atender a um filtro recorrente que a ordenação da tabela base não atende. Use um número reduzido de projeções para padrões de acesso importantes que a ordenação base não consegue atender com eficiência.
As projeções armazenam dados adicionais de índice ou coluna e acrescentam trabalho durante a inserção e a mesclagem; uma projeção de coluna completa duplica as colunas que armazena. O uso intenso de projeções também pode aumentar o trabalho necessário para escolher uma projeção ideal no momento da consulta. Para grandes implantações com muitos padrões de acesso distintos, menos projeções ou tabelas separadas projetadas para finalidades específicas costumam ser mais fáceis de operar. Consulte Visões materializadas versus projeções ao escolher entre esses mecanismos.
Adicione uma ordenação alternativa para consultas que filtram por tipo de pagamento e horário de retirada, continuando a consultar a tabela de origem:
EXPLAIN projections = 1 para confirmar se o ClickHouse seleciona a projeção e lê menos linhas ou bytes. Meça também a sobrecarga de inserção e armazenamento antes de aplicar esse padrão em larga escala.
Pré-calcule trabalhos repetitivos
- Use quando: As mesmas transformações ou agregações dominam repetidamente o tempo de consulta.
- Altere: Mova computações repetitivas para a ingestão, uma atualização agendada ou um layout de dados específico.
- Valide: Confirme que a consulta lê um resultado menor e realiza menos computações no momento da consulta, enquanto o trabalho de ingestão ou atualização permanece aceitável.
Cada seção inclui uma implementação básica, o principal trade-off operacional e uma forma de validar o resultado.
View materializada incremental
sum(trip_count) agrupado por pickup_date para combinar, durante a consulta, as linhas que aguardam uma mesclagem em segundo plano. A visualização processa apenas novos inserts; portanto, faça o backfill dos dados de origem existentes separadamente. Valide a alteração comparando a duração e o número de linhas lidas com a agregação original e, em seguida, confirme que o trabalho adicional de inserção é aceitável.
View materializada atualizável
system.view_refreshes para confirmar que a duração, o status e a frequência das atualizações são adequados à carga de trabalho.
Tabela dedicada
Nullable dessas duas colunas de destino. Confirme se esse tratamento atende aos requisitos de dados da carga de trabalho. O dashboard deve consultar explicitamente esta tabela, e o pipeline de ingestão deve mantê-la atualizada. Valide a alteração comparando as linhas e os bytes lidos, o uso de memória e a duração com a consulta na tabela de origem. Considere o armazenamento adicional e a manutenção do pipeline na decisão.