Introduction
Dans ce guide, nous verrons d’abord comment ClickHouse répartit une requête sur plusieurs shards via des tables distribuées, puis comment une requête peut tirer parti de plusieurs répliques pour son exécution.Dans une architecture shared-nothing, les clusters sont généralement répartis en plusieurs shards, chaque shard contenant un sous-ensemble de l’ensemble des données. Une table distribuée se place au-dessus de ces shards et fournit une vue unifiée de l’intégralité des données. Les lectures peuvent être envoyées à la table locale. L’exécution de la requête n’aura lieu que sur le shard spécifié, ou bien elle peut être envoyée à la table distribuée, auquel cas chaque shard exécutera la requête donnée. Le serveur sur lequel la table distribuée a été interrogée agrégera les données et renverra la réponse au client : La figure ci-dessus illustre ce qui se passe lorsqu’un client interroge une table distribuée :
- La requête SELECT est envoyée à une table distribuée sur un nœud choisi arbitrairement (via une stratégie round-robin ou après avoir été redirigée vers un serveur spécifique par un répartiteur de charge). Ce nœud va alors jouer le rôle de coordinateur.
- Le nœud localise chaque shard qui doit exécuter la requête à l’aide des informations spécifiées par la table distribuée, puis la requête est envoyée à chaque shard.
- Chaque shard lit, filtre et agrège les données localement, puis renvoie un état fusionnable au coordinateur.
- Le nœud coordinateur fusionne les données, puis renvoie la réponse au client.
Architecture non shardée
Présentation des répliques parallèles
- La requête du client est envoyée à un nœud après être passée par un répartiteur de charge. Ce nœud devient le coordinateur de cette requête.
- Le nœud analyse l’index de chaque partie et sélectionne les bonnes parties et granules à traiter.
- Le coordinateur répartit la charge de travail en un ensemble de granules pouvant être attribués à différentes répliques.
- Chaque ensemble de granules est traité par les répliques correspondantes, puis un état fusionnable est envoyé au coordinateur une fois le traitement terminé.
- Enfin, le coordinateur fusionne tous les résultats des répliques puis renvoie la réponse au client.
- Certaines répliques peuvent être indisponibles.
- La réplication dans ClickHouse est asynchrone ; à un instant donné, certaines répliques peuvent ne pas avoir les mêmes parties.
- Il faut également gérer la tail latency.
- Le cache du système de fichiers varie d’une réplique à l’autre en fonction de l’activité sur chacune d’elles, ce qui signifie qu’une attribution aléatoire des tâches pourrait entraîner des performances moins bonnes en raison de la localité du cache.
Annonces
- La requête du client est envoyée à un nœud après être passée par un répartiteur de charge. Ce nœud devient le coordinateur de cette requête.
- Le nœud coordinateur envoie ensuite une requête pour récupérer les annonces de toutes les répliques du cluster. Les répliques peuvent avoir des vues légèrement différentes de l’ensemble actuel des parts d’une table. Il faut donc collecter ces informations afin d’éviter des décisions de planification incorrectes.
- Le nœud coordinateur utilise ensuite les annonces pour définir un ensemble de granules pouvant être attribuées aux différentes répliques. Ici, par exemple, on peut voir qu’aucune granule de la part 3 n’a été attribuée à la réplique 2, car cette réplique n’a pas indiqué cette part dans son annonce. Notez également qu’aucune tâche n’a été attribuée à la réplique 3, car la réplique n’a fourni aucune annonce.
- Une fois que chaque réplique a traité la requête sur son sous-ensemble de granules et que l’état fusionnable a été renvoyé au coordinateur, celui-ci fusionne les résultats et renvoie la réponse au client.
Coordination dynamique
- Les répliques indiquent au nœud coordinateur qu’elles sont en mesure de traiter des tâches, et peuvent également préciser la quantité de travail qu’elles peuvent prendre en charge.
- Le coordinateur attribue des tâches aux répliques.
- Les répliques 1 et 2 terminent leur tâche très rapidement. Elles demandent alors une autre tâche au nœud coordinateur.
- Le coordinateur attribue de nouvelles tâches aux répliques 1 et 2.
- Toutes les répliques ont maintenant terminé le traitement de leur tâche. Elles demandent davantage de tâches.
- Le coordinateur, à l’aide des annonces, vérifie quelles tâches restent à traiter, mais il n’en reste aucune.
- Le coordinateur indique aux répliques que tout a été traité. Il va maintenant fusionner tous les états fusionnables et répondre à la requête.
Gestion de la localité du cache
| Réplique 1 | Réplique 2 | Réplique 3 | |
|---|---|---|---|
| Part 1 | g1, g6, g7 | g2, g4, g5 | g3 |
| Part 2 | g1 | g2, g4, g5 | g3 |
| Part 3 | g1, g6 | g2, g4, g5 | g3 |
max_parallel_replicas est inférieur
au nombre de répliques, des répliques aléatoires sont alors sélectionnées pour l’exécution des requêtes.
Vol de tâches
Limitations
Si vous trouvez un ticket qui ne figure pas parmi les limitations indiquées ci-dessous et
soupçonnez les répliques parallèles d’en être la cause, veuillez ouvrir un ticket sur GitHub avec
le label
comp-parallel-replicas.| Limitation | Description |
|---|---|
| Requêtes complexes | Actuellement, les répliques parallèles fonctionnent assez bien pour les requêtes simples. Des couches de complexité comme les CTE, les sous-requêtes, les JOIN, les requêtes à structure non plate, etc. peuvent avoir un impact négatif sur les performances des requêtes. |
| Petites requêtes | Si vous exécutez une requête qui ne traite pas beaucoup de lignes, l’exécuter sur plusieurs répliques peut ne pas améliorer les performances, étant donné que le temps réseau nécessaire à la coordination entre les répliques peut entraîner des cycles supplémentaires dans l’exécution de la requête. Vous pouvez limiter ces problèmes en utilisant le paramètre : parallel_replicas_min_number_of_rows_per_replica. |
| Les répliques parallèles sont désactivés avec FINAL | |
| Les projections ne sont pas utilisées avec les répliques parallèles | |
| Données à forte cardinalité et agrégation complexe | Une agrégation à forte cardinalité qui doit envoyer beaucoup de données peut ralentir considérablement vos requêtes. |
| Compatibilité avec le nouvel analyseur | Le nouvel analyseur peut considérablement ralentir ou accélérer l’exécution des requêtes dans certains scénarios. |
| Paramètre | Description |
|---|---|
enable_parallel_replicas | 0 : désactivé1 : activé 2 : force l’utilisation d’une réplique parallèle et lèvera une exception si ce n’est pas le cas. |
cluster_for_parallel_replicas | Nom du cluster à utiliser pour la réplication parallèle ; si vous utilisez ClickHouse Cloud, utilisez default. |
max_parallel_replicas | Nombre maximal de répliques à utiliser pour exécuter la requête sur plusieurs répliques. Si un nombre inférieur au nombre de répliques du cluster est spécifié, les nœuds seront sélectionnés aléatoirement. Cette valeur peut également être surallouée pour tenir compte de la mise à l’échelle horizontale. |
parallel_replicas_min_number_of_rows_per_replica | Permet de limiter le nombre de répliques utilisées en fonction du nombre de lignes à traiter. Le nombre de répliques utilisées est défini par : estimated rows to read / min_number_of_rows_per_replica. |
enable_analyzer | L’exécution des requêtes avec des répliques parallèles n’est prise en charge que lorsque l’analyseur est activé |
Investiguer les problèmes liés aux répliques parallèles
system.query_log. Vous pouvez
également consulter la table system.events
pour voir tous les événements survenus sur le serveur, et vous pouvez utiliser la
table function clusterAllReplicas pour voir les tables sur tous les répliques
(si vous utilisez ClickHouse Cloud, utilisez default).
Query
Réponse
Réponse
Response
system.text_log contient également des informations sur l’exécution de requêtes utilisant des répliques parallèles :
Query
Réponse
Réponse
Response
EXPLAIN PIPELINE. Il met en évidence la manière dont ClickHouse
va exécuter une requête et quelles ressources seront utilisées pour
son exécution. Prenons la requête suivante comme exemple :
EXPLAIN PIPELINE (without parallel replica)
EXPLAIN PIPELINE (with parallel replica)