Quando usar dicionários vs JOINs
WHERE. Embora as versões mais recentes (24.12+) apliquem filtros antes de JOINs em muitos casos, isso nem sempre elimina essa sobrecarga. Com um dicionário, você chama dictGet inline, então as consultas só acontecem nas linhas que já passaram pela filtragem.
No entanto, dictGet nem sempre é a melhor escolha. Se você precisar chamar dictGet em uma grande porcentagem das linhas de uma tabela — por exemplo, em uma condição WHERE como dictGet('dict', 'elevation', id) > 1800 — pode ser melhor usar uma coluna comum com índices nativos. O ClickHouse pode usar PREWHERE para ignorar grânulos em uma coluna comum, mas dictGet é avaliado linha por linha, sem suporte a índice.
Como regra geral:
- Use dicionários para substituir JOINs com tabelas de dimensão pequenas, em que a chave de consulta já está disponível.
- Use colunas comuns e índices ao filtrar pelo valor consultado em muitas linhas.
Escolhendo um layout
LAYOUT controla a estrutura de dados interna do dicionário. Todos os layouts disponíveis estão documentados na referência de layouts.
Ao escolher um layout, use as seguintes diretrizes:
flat— o layout mais rápido (consulta simples por deslocamento em array), mas as chaves devem serUInt64e, por padrão, são limitadas a 500.000 (max_array_size). É o melhor para chaves inteiras com crescimento monotônico em tabelas de pequeno a médio porte. Distribuições esparsas de chaves (por exemplo, valores de chave 1 e 500.000) desperdiçam memória, já que o array é dimensionado com base na maior chave. Se você estiver esbarrando no limite de 500 mil, isso é um sinal para mudar parahashed_array.hashed_array— o padrão recomendado para a maioria dos casos de uso. Armazena atributos em arrays com uma tabela hash que mapeia chaves para índices no array. É quase tão rápido quantohashed, mas usa memória de forma mais eficiente, especialmente quando há muitos atributos.hashed— armazena o dicionário completo em uma tabela hash. Pode ser mais rápido quehashed_arrayquando há pouquíssimos atributos, mas consome mais memória à medida que o número de atributos cresce.complex_key_hashed/complex_key_hashed_array— use-os quando as chaves não puderem ser convertidas paraUInt64(por exemplo, chavesString). Eles seguem os mesmos trade-offs de desempenho que as versões sem chave complexa.sparse_hashed— troca CPU por menor uso de memória em comparação comhashed. Raramente é a melhor escolha — só é eficiente quando há um único atributo. Na maioria dos casos,hashed_arrayé mais adequado.cache/ssd_cache— armazenam em cache apenas as chaves acessadas com frequência. São úteis quando o conjunto de dados completo não cabe na memória, mas as consultas podem consultar a fonte em caso de cache miss. Não são recomendados para workloads sensíveis à latência.direct— consulta a fonte a cada consulta, sem armazenamento em memória. Use quando os dados mudam com frequência demais para serem armazenados em cache ou quando o dicionário é grande demais para caber na memória.
Monitoramento do uso de dicionários
system.dictionaries:
bytes_allocated— memória consumida pelo dicionário. Os dicionários armazenam dados sem compressão, portanto esse valor pode ser significativamente maior que o tamanho da tabela comprimida.hit_rateefound_rate— úteis para avaliar a eficácia do layoutcache.last_exception— verifique este campo quando um dicionário não conseguir ser carregado ou atualizado.