join_algorithm
Spécifie quel algorithme de JOIN est utilisé. Plusieurs algorithmes peuvent être spécifiés, et un algorithme disponible est choisi pour une requête donnée en fonction du type, de la strictness et du moteur de table. Le fait qu’un algorithme fondé sur le hachage déverse sur disque ne fait pas partie de ce choix :max_bytes_before_external_join / max_bytes_ratio_before_external_join constituent le seuil de déversement pour tous (et dès que l’une des deux valeurs est non nulle, enable_adaptive_memory_spill_scheduler peut déverser la jointure encore plus tôt, en cas de memory pressure), et max_rows_in_join / max_bytes_in_join une limite stricte pour tous, à moins que legacy_join_size_limits_trigger_spilling ne retransforme ces deux limites en déclencheurs de déversement sur disque. La valeur que vous choisissez détermine la manière dont une jointure déverse : grace_hash partitionne la table de droite dès le premier bloc, tandis que hash et parallel_hash la collectent en mémoire et basculent une fois le seuil franchi.
La plupart des algorithmes n’affectent une requête que lorsqu’ils sont sélectionnés pour celle-ci. Certains, cependant, modifient la planification du simple fait d’être répertoriés — même en tant que solution de repli de priorité inférieure qui n’est finalement pas sélectionnée — car la décision est prise avant que l’algorithme ne soit choisi. Il existe deux effets de ce type :
- L’inférence de type des clés de jointure devient plus stricte (une jointure par fusion ne peut pas joindre des clés de types différents, par exemple
StringetNullable(String)). Cela peut modifier les types de résultat des colonnesUSINGet entraîner l’échec d’une jointure avec une table du moteurJoinavecTYPE_MISMATCH. Déclenché parfull_sorting_mergeetparallel_full_sorting_merge. ORDER BY ... LIMITdu côté préservé d’une jointure reçoit un tri explicite au lieu d’une lecture dans l’ordre de la clé primaire, car la jointure est supposée interrompre la lecture ordonnée (une jointure par fusion insère son propre tri avant la jointure ; une jointure par fusion partielle retrie les blocs de gauche ; une jointure pouvant produire des blocs retardés ne propage pas non plus la lecture ordonnée). Le résultat est le même, mais le plan est moins efficace. Déclenché parfull_sorting_merge,parallel_full_sorting_merge,partial_merge,prefer_partial_merge,grace_hashetauto, ainsi que par une valeur non nulle demax_bytes_before_external_join/max_bytes_ratio_before_external_join.
hash ou un autre algorithme. Si cela n’est pas souhaitable, ne répertoriez pas les algorithmes ci-dessus dans join_algorithm pour les requêtes concernées.
Valeurs possibles :
- grace_hash
grace_hash est externe dès le premier bloc : la table de droite est partitionnée immédiatement, là où hash et parallel_hash la collectent d’abord en mémoire et ne la partitionnent qu’une fois le seuil de déversement franchi. Choisissez-le lorsque vous savez déjà que le côté droit ne tiendra pas en mémoire et que vous souhaitez éviter la phase en mémoire. Le seuil de déversement lui-même est celui qu’utilisent tous les algorithmes de hachage, max_bytes_before_external_join / max_bytes_ratio_before_external_join, et l’une des deux valeurs doit être non nulle, sauf si legacy_join_size_limits_trigger_spilling est activé. Sans seuil, grace_hash est ignoré au profit de l’algorithme suivant dans la liste, et rejeté s’il est le seul.
La première phase d’une jointure grace lit la table de droite et la découpe en N buckets en fonction de la valeur de hachage des colonnes de clé (initialement, N vaut grace_hash_join_initial_buckets). Cela est fait de manière à garantir que chaque bucket puisse être traité indépendamment. Les lignes du premier bucket sont ajoutées à une hash table en mémoire tandis que les autres sont enregistrées sur disque. Si la hash table dépasse le seuil de déversement, le nombre de buckets est augmenté ainsi que le bucket affecté à chaque ligne. Toutes les lignes qui n’appartiennent pas au bucket courant sont vidées et réaffectées.
Prend en charge INNER/LEFT/RIGHT/FULL ALL/ANY JOIN.
- hash
OR dans la section JOIN ON.
Lors de l’utilisation de l’algorithme hash, la partie droite du JOIN est chargée en RAM.
- parallel_hash
hash qui découpe les données en buckets et construit plusieurs hashtables simultanément au lieu d’une seule afin d’accélérer ce processus.
Lors de l’utilisation de l’algorithme parallel_hash, la partie droite du JOIN est chargée en RAM.
- partial_merge
RIGHT JOIN et FULL JOIN ne sont pris en charge qu’avec la strictness ALL (SEMI, ANTI, ANY et ASOF ne sont pas pris en charge).
Lors de l’utilisation de l’algorithme partial_merge, ClickHouse trie les données et les écrit sur le disque. L’algorithme partial_merge de ClickHouse diffère légèrement de l’implémentation classique. Tout d’abord, ClickHouse trie la table de droite par clés de jointure en blocs et crée un index min-max pour les blocs triés. Il trie ensuite des parties de la table de gauche par clé de jointure et les joint à la table de droite. L’index min-max est également utilisé pour ignorer les blocs inutiles de la table de droite.
- direct
direct (également appelé boucle imbriquée) effectue une recherche dans la table de droite en utilisant les lignes de la table de gauche comme clés.
Il est pris en charge par des stockages spéciaux tels que Dictionary, EmbeddedRocksDB et les tables MergeTree.
Pour les tables MergeTree, l’algorithme pousse directement les filtres de clé de jointure vers la couche de stockage. Cela peut être plus efficace lorsque la clé peut utiliser l’index de clé primaire de la table pour les recherches ; sinon, il effectue un parcours complet de la table de droite pour chaque bloc de la table de gauche.
Prend en charge les jointures INNER et LEFT, et uniquement des clés de jointure d’égalité sur une seule colonne, sans autre condition.
- auto
auto, la jointure hash est essayée en premier, et l’algorithme bascule à la volée vers un autre algorithme si la limite de mémoire est dépassée.
- full_sorting_merge
- ie_join
JOIN dont la section ON comporte deux comparaisons d’inégalité (<, <=, >, >=) entre des expressions des tables jointes. Prend en charge ALL INNER/LEFT/RIGHT/FULL JOIN et les SEMI/ANTI LEFT/RIGHT JOIN.
La position dans la liste définit la priorité : répertorié après les autres algorithmes, comme dans la valeur par défaut, IEJoin est utilisé uniquement lorsqu’ils ne s’appliquent pas (la section ON ne comporte aucune condition d’égalité) ; répertorié en premier, il est utilisé chaque fois que la section ON comporte deux conditions d’inégalité. Les conditions restantes (y compris les égalités) sont appliquées comme filtre sur le résultat de la jointure pour ALL INNER JOIN, et évaluées au sein de l’opérateur comme condition résiduelle affectant la correspondance pour les autres types. Lorsque la section ON comporte plus de deux conditions d’inégalité éligibles, les deux utilisées par l’algorithme sont choisies selon leur sélectivité estimée à partir des statistiques min/max des colonnes (voir le type basic dans Statistiques de colonnes) ; lorsque les estimations ne sont pas disponibles (aucune statistique ou use_statistics est désactivé), les deux premières dans l’ordre syntaxique sont utilisées. Sans ie_join dans la liste, une INNER JOIN ne comportant que des conditions d’inégalité est exécutée comme une CROSS JOIN avec un filtre, et les autres types ne sont pas pris en charge.
Les deux entrées sont accumulées en mémoire avant la jointure : max_rows_in_join et max_bytes_in_join limitent l’entrée accumulée des deux côtés ensemble (et non uniquement du côté droit), l’action en cas de dépassement de capacité étant définie par join_overflow_mode ; les index de tri que l’opérateur construit par-dessus l’entrée accumulée ne sont pas comptabilisés dans la limite. L’opérateur de jointure lui-même s’exécute dans un seul thread ; seuls les tris des entrées précédant la jointure sont parallélisés.
- parallel_full_sorting_merge
full_sorting_merge, mais les jointures d’égalité compatibles avec le hachage sont partitionnées par le hachage des clés de jointure en jointures par fusion indépendantes par partition qui s’exécutent en parallèle (jusqu’à max_threads), au lieu d’une seule jointure par fusion. Cela conserve la faible consommation mémoire en flux d’une jointure par fusion tout en utilisant tous les threads, et le résultat n’est pas ordonné.
Le partitionnement par hachage sur les clés de jointure n’est appliqué qu’aux jointures d’égalité simples sur des types de clés dont le hachage concorde avec la comparaison de jointure par fusion, et uniquement lorsque aucun des deux côtés n’est déjà trié. Il est ignoré dans les cas suivants :
- Les jointures
ASOF, et les types de clés à virgule flottante /JSON/Object/Dynamic: leurs hachages ne sont pas cohérents avec la comparaison de jointure par fusion, de sorte que des clés égales pourraient se retrouver dans des partitions différentes. - Les côtés déjà triés (une lecture MergeTree dans l’ordre, ou toute entrée prétriée) : une dispersion préservant l’ordre dans les fusions par partition peut provoquer un interblocage du pipeline. La lecture dans l’ordre et son optimisation
read_in_order_use_virtual_rowsont conservées à la place. - Pendant que l’initiateur construit un plan distribué (
make_distributed_plan), car le tri dispersé n’est pas sérialisable pour une exécution distante. Le plan local à fragment unique et les fragments par worker se réoptimisent avec ce paramètre désactivé, afin qu’ils puissent tout de même être partitionnés.
full_sorting_merge, et les côtés MergeTree lus dans l’ordre peuvent toujours être partitionnés à la source par plages de clé primaire (qui ordonnent selon la même comparaison que celle utilisée par la jointure, de sorte que les clés égales restent ensemble) lorsque query_plan_join_shard_by_pk_ranges est activé.
- prefer_partial_merge
partial_merge si possible, sinon il utilise hash. Deprecated, identique à partial_merge,hash.
- default (deprecated)
direct,hash, c’est-à-dire essayer d’utiliser la jointure directe puis la jointure par hachage (dans cet ordre).
join_any_take_last_row
Modifie le comportement des opérations de jointure de typeANY lorsque la table de droite contient plus d’une ligne correspondante pour une clé.
Ce paramètre s’applique aux tables utilisant le moteur
Join et aux algorithmes de jointure basés sur le hachage.Si une jointure est construite en parallèle, l’ordre des lignes peut être non déterministe. Cela signifie que join_any_take_last_row = 1 peut renvoyer une ligne de manière non déterministe pour les requêtes ANY JOIN.- 0 — Si la table de droite contient plus d’une ligne correspondante, seule la première trouvée est utilisée pour la jointure.
- 1 — Si la table de droite contient plus d’une ligne correspondante, seule la dernière trouvée est utilisée pour la jointure.
join_default_strictness
Définit la strictness par défaut des clauses JOIN. Valeurs possibles :ALL— Si la table de droite comporte plusieurs lignes correspondantes, ClickHouse crée un produit cartésien à partir de ces lignes. Il s’agit du comportementJOINordinaire du SQL standard.ANY— Si la table de droite comporte plusieurs lignes correspondantes, seule la première trouvée est utilisée pour la jointure. Si la table de droite ne comporte qu’une seule ligne correspondante, les résultats deANYetALLsont identiques.ASOF— Pour joindre des séquences avec une correspondance incertaine.Chaîne vide— SiALLouANYn’est pas spécifié dans la requête, ClickHouse lève une exception.
join_on_disk_max_files_to_merge
Limite le nombre de fichiers autorisés pour le tri parallèle lors des opérations MergeJoin exécutées sur disque. Plus la valeur du paramètre est élevée, plus la quantité de RAM utilisée augmente et moins les E/S disque sont nécessaires. Valeurs possibles :- Tout entier positif à partir de 2.
join_output_by_rowlist_perkey_rows_threshold
La limite inférieure de la moyenne de lignes par clé dans la table de droite, utilisée pour déterminer s’il faut produire la sortie sous forme de liste de lignes dans un hash join.join_overflow_mode
Définit l’action effectuée par ClickHouse lorsqu’une jointure atteint l’une des limites suivantes : Toutes les valeurs dejoin_algorithm
basées sur le hachage respectent ce paramètre, y compris celles qui effectuent un déversement sur disque : atteindre la
limite arrête la requête au lieu de déclencher un déversement. L’exception est
legacy_join_size_limits_trigger_spilling : lorsqu’il est activé, la partie d’une jointure qui
s’exécute déjà sur disque continue de se déverser au lieu d’appliquer ce paramètre.
ie_join le respecte également, sur l’entrée qu’il accumule des deux côtés. partial_merge gère
toujours ces limites en changeant de stratégie — voir
join_algorithm.
Valeurs possibles :
THROW— ClickHouse lève une exception et arrête la requête.BREAK— ClickHouse arrête la requête sans lever d’exception.
THROW.
Voir aussi