JOIN, com uma ampla variedade de algoritmos de junção. Para maximizar o desempenho, recomendamos seguir as sugestões de otimização de junção listadas neste guia.
- Para um desempenho ideal, você deve procurar reduzir o número de
JOINs nas consultas, especialmente em workloads analíticas em tempo real que exigem desempenho na casa dos milissegundos. Procure limitar cada consulta a no máximo 3 ou 4 junções. Detalhamos várias formas de minimizar junções na seção de modelagem de dados, incluindo desnormalização, Dictionaries e visões materializadas. - A partir do ClickHouse 24.12, o planejador de consultas reordena automaticamente junções entre duas tabelas para colocar a tabela menor no lado direito, visando ao melhor desempenho. Na versão 25.9, isso foi estendido para otimizar a ordem das junções em consultas que envolvem três ou mais tabelas.
- Se a sua consulta exigir uma junção direta, ou seja, um
LEFT ANY JOIN, como mostrado abaixo, recomendamos usar Dictionaries sempre que possível.
- Ao fazer junções internas, em geral é mais eficiente escrevê-las como subconsultas usando a cláusula
IN. Considere as consultas a seguir, que são funcionalmente equivalentes. Ambas encontram o número depostsque não mencionam ClickHouse na pergunta, mas mencionam emcomments.
ANY INNER JOIN, em vez de apenas um INNER JOIN, pois não queremos o produto cartesiano, ou seja, queremos apenas uma correspondência para cada post.
Esse junção pode ser reescrito usando uma subconsulta, melhorando significativamente o desempenho:
JOIN. Considere o exemplo abaixo, em que queremos calcular o número de votos positivos em posts relacionados a Java desde 2020.
Uma consulta ingênua, com a tabela maior no lado esquerdo, leva 56s para ser concluída:
INNER JOIN para uma subconsulta, como mencionado anteriormente, mantendo o filtro tanto na consulta externa quanto na interna.
Escolhendo um algoritmo de junção
Esses algoritmos determinam como uma consulta com junção é planejada e executada. Por padrão, o ClickHouse usa o algoritmo direct junção ou hash junção com base no tipo e na strictness da junção utilizado, bem como no engine das tabelas unidas. Como alternativa, o ClickHouse pode ser configurado para escolher de forma adaptativa e alterar dinamicamente o algoritmo de junção em tempo de execução, dependendo da disponibilidade e do uso de recursos: quando
join_algorithm=auto, o ClickHouse tenta primeiro o algoritmo hash junção e, se o limite de memória desse algoritmo for excedido, ele é alterado automaticamente para partial merge junção. Você pode verificar qual algoritmo foi escolhido por meio do trace logging. O ClickHouse também permite especificar diretamente o algoritmo de junção desejado por meio da configuração join_algorithm.
Os tipos de JOIN compatíveis com cada algoritmo de junção são mostrados abaixo e devem ser considerados antes da otimização:
Uma descrição completa e detalhada de cada algoritmo de
JOIN pode ser encontrada aqui, incluindo seus prós, contras e propriedades de escalabilidade.
A seleção dos algoritmos de junção apropriados depende de você querer otimizar o uso de memória ou o desempenho.
Otimizando o desempenho de junção
-
(1) Se os dados da tabela do lado direito puderem ser pré-carregados em uma estrutura de dados chave-valor em memória e de baixa latência, por exemplo, um dicionário, e se a chave de junção corresponder ao atributo de chave do armazenamento chave-valor subjacente, e se a semântica de
LEFT ANY JOINfor adequada, então o direct junção pode ser usado e oferece a abordagem mais rápida. - (2) Se a ordem física das linhas da sua tabela corresponder à ordem de classificação da chave de junção, então depende. Nesse caso, o full sorting merge junção ignora a fase de ordenação, o que resulta em uso de memória significativamente menor e, dependendo do volume de dados e da distribuição dos valores da chave de junção, tempos de execução mais rápidos do que alguns dos algoritmos de hash junção.
- (3) Se a tabela da direita couber na memória, mesmo com a sobrecarga adicional de uso de memória do parallel hash junção, então esse algoritmo ou o hash junção pode ser mais rápido. Isso depende do volume de dados, dos tipos de dados e da distribuição dos valores das colunas da chave de junção.
- (4) Se a tabela da direita não couber na memória, então, novamente, depende. O ClickHouse oferece três algoritmos de junção que não ficam restritos à memória. Os três gravam temporariamente dados em disco. Full sorting merge junção e partial merge junção exigem ordenação prévia dos dados. Já o grace hash junção constrói tabelas hash a partir dos dados. Dependendo do volume de dados, dos tipos de dados e da distribuição dos valores das colunas da chave de junção, pode haver cenários em que construir tabelas hash a partir dos dados seja mais rápido do que ordená-los. E vice-versa.
Otimizando para memória
- (1) Se a ordem física das linhas da sua tabela corresponder à ordem de classificação da chave da junção, o uso de memória do full sorting merge join será o menor possível. Como benefício adicional, a velocidade da junção também será boa, porque a fase de ordenação fica desativada.
- (2) O grace hash join pode ser ajustado para um uso de memória muito baixo configurando um número alto de buckets, em troca de menor velocidade da junção. O partial merge join usa intencionalmente pouca memória principal. O full sorting merge join com ordenação externa habilitada geralmente usa mais memória do que o partial merge join (supondo que a ordem das linhas não corresponda à ordem de classificação da chave), mas oferece um tempo de execução da junção significativamente melhor.