- Melhorar o desempenho das consultas, especialmente quando usados com
JOINs - Enriquecer os dados ingeridos em tempo real sem desacelerar o processo de ingestão
Acelerando junções usando um Dicionário
Dicionários podem ser usados para acelerar um tipo específico deJOIN: o tipo LEFT ANY, em que a chave da junção precisa corresponder ao atributo-chave do armazenamento subjacente de chave-valor.
Se esse for o caso, o ClickHouse pode aproveitar o dicionário para executar um Direct Join. Esse é o algoritmo de junção mais rápido do ClickHouse e se aplica quando o motor de tabela da tabela do lado direito oferece suporte a solicitações de chave-valor de baixa latência. O ClickHouse tem três motores de tabela que oferecem isso: Join (que é basicamente uma tabela hash pré-calculada), EmbeddedRocksDB e Dicionário. Vamos descrever a abordagem baseada em dicionário, mas o funcionamento é o mesmo para os três motores.
O algoritmo de junção direta exige que a tabela da direita seja baseada em um dicionário, de modo que os dados dessa tabela a serem unidos já estejam presentes na memória na forma de uma estrutura de dados de chave-valor de baixa latência.
Exemplo
JOIN entre as tabelas posts e votes:
Use conjuntos de dados menores no lado direito deEmbora esta consulta seja rápida, ela exige que escrevamos oJOIN: Esta consulta pode parecer mais verbosa do que o necessário, com a filtragem dePostIds ocorrendo tanto na consulta externa quanto nas subconsultas. Esta é uma otimização de desempenho que garante um tempo de resposta rápido para a consulta. Para obter o melhor desempenho, sempre garanta que o lado direito doJOINseja o menor conjunto possível. Para ver dicas sobre como otimizar o desempenho deJOINe entender os algoritmos disponíveis, recomendamos esta série de artigos no blog.
JOIN com cuidado para obter um bom desempenho. O ideal seria simplesmente filtrar os posts para aqueles que contêm “SQL” antes de analisar as contagens de UpVote e DownVote para o subconjunto de blogs e calcular nossa métrica.
Aplicando um dicionário
votes:
No exemplo abaixo, os dados do nosso dicionário vêm de uma tabela do ClickHouse. Embora essa seja a fonte mais comum de dicionários, há várias fontes compatíveis, incluindo arquivos, http e bancos de dados como o Postgres. Como veremos, os dicionários podem ser atualizados automaticamente, o que é ideal para garantir que pequenos conjuntos de dados sujeitos a mudanças frequentes estejam disponíveis para direct joins.Nosso dicionário exige uma chave primária sobre a qual os lookups serão feitos. Conceitualmente, isso é idêntico à chave primária de um banco de dados transacional e deve ser único. Nossa consulta acima exige um lookup na chave de join —
PostId. Por sua vez, o dicionário deve ser preenchido com o total de votos positivos e negativos por PostId da nossa tabela votes. Aqui está a consulta para obter esses dados do dicionário:
Na versão OSS autogerenciada, o comando acima precisa ser executado em todos os nós. No ClickHouse Cloud, o dicionário será replicado automaticamente para todos os nós. Isso foi executado em um nó do ClickHouse Cloud com 64GB de RAM, levando 36s para carregar.Para confirmar a memória consumida pelo nosso dicionário:
PostId específico com uma simples função dictGet. Abaixo, recuperamos os valores da postagem 11227902:
Enriquecimento em tempo de consulta
Enriquecimento no momento da indexação
No exemplo acima, usamos um dicionário em tempo de consulta para eliminar uma junção. Os dicionários também podem ser usados para enriquecer linhas no momento da inserção. Isso normalmente é apropriado se o valor do enriquecimento não muda e está em uma fonte externa que pode ser usada para preencher o dicionário. Nesse caso, enriquecer a linha no momento da inserção evita a consulta no dicionário em tempo de consulta.Evite layouts de dicionário baseados em cache para o enriquecimento no momento da inserção quando latência previsível e disponibilidade da fonte forem importantes. Cada servidor mantém seu próprio cache local, e uma reinicialização ou substituição o deixa vazio, fazendo com que os inserts dependam de consultas com cache frio na fonte do dicionário. O autoscaling e a substituição gerenciada de nós no ClickHouse Cloud tornam essa situação mais provável. Escolha um layout que carregue o dicionário completo em cada servidor. Consulte Dicionários de cache em caminhos de ingestão.
Location de um usuário no Stack Overflow nunca mude (na prática, muda) — especificamente, a coluna Location da tabela users. Suponha que queremos fazer uma consulta analítica na tabela de posts por localização. Ela contém um UserId.
Um dicionário fornece um mapeamento do ID do usuário para a localização, com base na tabela users:
Omitimos usuários comPara aproveitar esse dicionário no momento da inserção na tabela Posts, precisamos modificar o schema:Id < 0, o que nos permite usar o tipo de dicionárioHashed. Usuários comId < 0são usuários do sistema.
Location é declarada como uma coluna MATERIALIZED. Isso significa que o valor pode ser fornecido como parte de uma consulta INSERT e será sempre calculado.
O ClickHouse também oferece suporte a colunas DEFAULT` (em que o valor pode ser inserido ou calculado, caso não seja fornecido).
Para preencher a tabela, podemos usar o habitual INSERT INTO SELECT a partir do S3:
Tópicos avançados sobre dicionários
Atualizando dicionários
LIFETIME para o dicionário de MIN 600 MAX 900. LIFETIME é o intervalo de atualização do dicionário, e esses valores fazem com que ele seja recarregado periodicamente em um intervalo aleatório entre 600 e 900s. Esse intervalo aleatório é necessário para distribuir a carga na origem do dicionário ao atualizar em um grande número de servidores. Durante as atualizações, a versão antiga de um dicionário ainda pode ser consultada; apenas a carga inicial bloqueia consultas. Observe que definir (LIFETIME(0)) impede a atualização dos dicionários.
Os dicionários podem ser recarregados à força usando o comando SYSTEM RELOAD DICTIONARY.
Para origens de banco de dados, como ClickHouse e Postgres, você pode configurar uma consulta que atualizará os dicionários apenas se eles realmente tiverem mudado (a resposta da consulta determina isso), em vez de em um intervalo periódico. Mais detalhes podem ser encontrados aqui.
Outros tipos de dicionários
Leitura adicional
- Boas práticas de dicionário — seleção de layout, dicionários vs junções, monitoramento
- Usando Dicionários para Acelerar Consultas
- Configuração avançada de Dicionários