Antes de começar
nyc_taxi.trips_small_inferred. Crie-a e carregue-a caso ainda não tenha feito isso:
Configure o conjunto de dados de exemplo
Configure 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.
Visão geral do processo
- Execute três consultas independentes de carga de trabalho no esquema inferido para estabelecer uma referência.
- Crie uma tabela com tipos de coluna mais precisos, carregue os mesmos dados e execute as consultas novamente.
- Crie outra tabela com o mesmo esquema otimizado e uma chave de ordenação e execute as consultas novamente.
Defina a carga de trabalho de referência
Essas configurações ajudam a tornar comparáveis as execuções repetidas durante os testes. Restaure os valores anteriores após concluir as medições.
system.query_log.
Filtrar por velocidade calculada da viagem
Agregar viagens em um intervalo de datas
Filtrar por número de passageiros
As três consultas leram aproximadamente 329 milhões de linhas, um número próximo ao total de linhas da tabela. Isso indica a possibilidade de melhorar dois aspectos distintos da carga de trabalho: reduzir o custo de processamento das colunas selecionadas e, quando os filtros permitirem, reduzir o número de linhas selecionadas.
Otimize o esquema
Evite colunas Nullable desnecessárias
Nullable armazena uma máscara de valores nulos além de seus valores. Mantenha Nullable quando a distinção entre um valor nulo e o valor padrão do tipo for relevante, mas evite-o em colunas que têm garantia de sempre conter um valor.
Conte os valores nulos nas colunas usadas no esquema de exemplo:
ratecode_id, mta_tax e payment_type contêm valores nulos neste conjunto de dados. O esquema otimizado mantém Nullable nessas colunas e o remove das demais.
Use LowCardinality para valores repetidos
LowCardinality usa codificação de dicionário e pode reduzir o armazenamento e o processamento de colunas com muitos valores repetidos. Verifique o número de valores distintos antes de aplicá-la:
LowCardinality, embora o impacto ainda deva ser medido para a carga de trabalho. Cerca de 10.000 valores distintos é um ponto de partida útil para identificar candidatas, não um limite fixo.
Escolha tipos de dados mais precisos
Int64 ou Float64 inferido:
UInt8, embora passenger_count atinja o valor máximo de 255. O exemplo também usa Float32 para trip_distance e Decimal32 para valores monetários. Todos os valores deste conjunto de dados cabem nos intervalos de destino, e o exemplo aceita a menor precisão de ponto flutuante e a precisão monetária em centavos porque a carga de trabalho compara resultados agregados. Mantenha os tipos de origem mais abrangentes quando forem necessários valores exatos da origem. O exemplo substitui as colunas DateTime64 inferidas por DateTime no mesmo fuso horário UTC, pois as consultas do exemplo não exigem precisão de frações de segundo.
Essas escolhas são específicas deste conjunto de dados. Confirme os requisitos de intervalo, precisão e capacidade de aceitar valores nulos dos dados de produção antes de aplicar as mesmas alterações.
Aplique as alterações de esquema
nyc_taxi.trips_small_inferred por nyc_taxi.trips_small_no_pk e execute novamente as três consultas. O exemplo original registrou os seguintes resultados representativos:
As consultas continuam lendo o mesmo número de linhas, mas o esquema otimizado reduz a quantidade de dados representada por essas linhas. Assim, a duração da consulta e o pico de memória melhoram sem alterar a seleção de dados.
Compare o tamanho em disco das duas tabelas:
Otimize a chave de ordenação
MergeTree, a chave de ordenação determina como as linhas são organizadas em disco. O ClickHouse cria um índice primário esparso com base nessa ordenação, o que permite ignorar grânulos que não podem atender aos filtros de uma consulta. Diferentemente de uma chave primária em muitos bancos de dados transacionais, ela não impõe exclusividade.
A chave de ordenação deve refletir os filtros usados em consultas recorrentes importantes. A ordem das colunas é importante: uma chave é mais eficaz quando a consulta filtra por um prefixo útil. Colunas com menor cardinalidade às vezes são boas opções para as primeiras posições da chave quando são filtradas com frequência, e um componente de tempo costuma ser útil para cargas de trabalho baseadas em tempo. Para orientações detalhadas sobre a seleção, consulte Escolhendo uma chave primária.
Neste exemplo, use (passenger_count, pickup_datetime, dropoff_datetime). passenger_count tem poucos valores distintos e é usado no filtro de contagem de passageiros, enquanto pickup_datetime é usado na agregação por intervalo de datas. Embora pickup_datetime não seja a primeira coluna, o ClickHouse ainda pode usar valores de colunas-chave posteriores para excluir dados quando a coluna inicial não é restringida. Em geral, filtrar por um prefixo útil da chave de ordenação proporciona uma poda mais eficiente.
Aplique a alteração na chave de ordenação
nyc_taxi.trips_small_pk e execute novamente as três consultas.
Compare os resultados
A otimização do esquema reduz o armazenamento e torna os valores selecionados mais eficientes de processar. A chave de ordenação proporciona a maior melhoria adicional para a agregação por intervalo de datas, pois o ClickHouse pode ignorar grânulos fora desse intervalo. O filtro por número de passageiros também lê menos linhas porque filtra pela primeira coluna-chave. O filtro de velocidade calculada ainda lê a tabela inteira porque sua condição de filtragem é derivada de
pickup_datetime, dropoff_datetime e trip_distance, e não de um prefixo útil da chave de ordenação.
Inspecione a agregação por intervalo de datas com EXPLAIN indexes = 1:
No ClickHouse 25.9 e em versões posteriores, essas configurações garantem que
EXPLAIN informe os índices usados e as partes e os grânulos que eles descartam.Aplique o método à sua carga de trabalho
- Registre a duração de referência, as linhas e os bytes lidos e o pico de memória.
- Verifique se as colunas selecionadas usam tipos desnecessariamente amplos ou permissivos.
- Aplique e meça alterações de esquema sem alterar o layout dos dados.
- Teste uma chave de ordenação com base nos filtros usados por consultas recorrentes importantes.
- Compare os dados selecionados com
EXPLAIN indexes = 1e execute novamente as consultas de referência em condições comparáveis.