- Améliorer les performances des requêtes, en particulier avec les
JOIN - Enrichir les données ingérées à la volée sans ralentir le processus d’ingestion
Accélérer les jointures à l’aide d’un dictionnaire
JOIN : le type LEFT ANY, dans lequel la clé de jointure doit correspondre à l’attribut clé du stockage clé-valeur sous-jacent.
Dans ce cas, ClickHouse peut exploiter le dictionnaire pour effectuer une Direct Join. Il s’agit de l’algorithme de jointure le plus rapide de ClickHouse. Il s’applique lorsque le moteur de table sous-jacent de la table de droite prend en charge des requêtes clé-valeur à faible latence. ClickHouse propose trois moteurs de table qui le permettent : Join (qui est essentiellement une table de hachage précalculée), EmbeddedRocksDB et Dictionary. Nous allons décrire l’approche basée sur les dictionnaires, mais le mécanisme est le même pour ces trois moteurs.
L’algorithme de jointure directe exige que la table de droite repose sur un dictionnaire, afin que les données à joindre de cette table soient déjà présentes en mémoire sous la forme d’une structure de données clé-valeur à faible latence.
Exemple
JOIN entre les tables posts et votes :
Utilisez des ensembles de données plus petits du côté droit deBien que cette requête soit rapide, elle nous oblige à écrire leJOIN: Cette requête peut sembler plus détaillée que nécessaire, puisque le filtrage sur lesPostIdintervient à la fois dans la requête externe et dans la sous-requête. Il s’agit d’une optimisation des performances qui garantit un temps de réponse rapide. Pour des performances optimales, veillez toujours à ce que le côté droit duJOINsoit l’ensemble le plus petit possible. Pour des conseils sur l’optimisation des performances desJOINet pour mieux comprendre les algorithmes disponibles, nous recommandons cette série d’articles de blog.
JOIN avec soin pour obtenir de bonnes performances. Dans l’idéal, nous filtrerions simplement les posts pour ne conserver que ceux contenant “SQL”, avant d’examiner les nombres de UpVote et de DownVote pour le sous-ensemble de blogs afin de calculer notre métrique.
Utilisation d’un dictionnaire
votes :
Dans l’exemple ci-dessous, les données de notre dictionnaire proviennent d’une table ClickHouse. S’il s’agit de la source de dictionnaire la plus courante, plusieurs sources sont prises en charge, notamment des fichiers, http et des bases de données, y compris Postgres. Comme nous allons le montrer, les dictionnaires peuvent être actualisés automatiquement, ce qui en fait un moyen idéal de garantir que de petits jeux de données fréquemment modifiés sont disponibles pour des jointures directes.Notre dictionnaire nécessite une clé primaire sur laquelle les recherches seront effectuées. Conceptuellement, elle est identique à la clé primaire d’une base de données transactionnelle et doit être unique. Notre requête ci-dessus nécessite une recherche sur la clé de jointure,
PostId. Le dictionnaire doit ensuite être alimenté avec le total des votes positifs et négatifs par PostId à partir de notre table votes. Voici la requête permettant d’obtenir les données de ce dictionnaire :
Dans une installation OSS autogérée, la commande ci-dessus doit être exécutée sur tous les nœuds. Dans ClickHouse Cloud, le dictionnaire sera automatiquement répliqué sur tous les nœuds. L’exemple ci-dessus a été exécuté sur un nœud ClickHouse Cloud avec 64GB de RAM, et le chargement a pris 36s.Pour vérifier la mémoire consommée par notre dictionnaire :
PostId donné peut désormais se faire à l’aide d’une simple fonction dictGet. Ci-dessous, nous récupérons les valeurs pour le post 11227902 :
Enrichissement à l’exécution de la requête
Enrichissement au moment de l’indexation
Location d’un utilisateur dans Stack Overflow ne change jamais (en réalité, il change) — plus précisément, la colonne Location de la table users. Supposons que nous voulions exécuter une requête analytique sur la table posts par lieu. Celle-ci contient un UserId.
Un dictionnaire fournit une correspondance entre l’identifiant d’un utilisateur et son lieu, en s’appuyant sur la table users :
Nous excluons les utilisateurs dont l’Pour exploiter ce dictionnaire au moment de l’insert dans la table posts, nous devons modifier le schéma :Id < 0, ce qui nous permet d’utiliser le type de DictionaryHashed. Les utilisateurs dont l’Id < 0sont des utilisateurs système.
Location est déclarée comme une colonne MATERIALIZED. Cela signifie que la valeur peut être fournie dans une requête INSERT et qu’elle sera toujours calculée.
ClickHouse prend également en charge les colonnes DEFAULT (où la valeur peut être insérée ou calculée si elle n’est pas fournie).
Pour alimenter la table, nous pouvons utiliser l’habituel INSERT INTO SELECT depuis S3 :
Aspects avancés des dictionnaires
Actualisation des dictionnaires
LIFETIME pour le dictionnaire de MIN 600 MAX 900. LIFETIME est l’intervalle de mise à jour du dictionnaire ; les valeurs indiquées ici entraînent un rechargement périodique à un intervalle aléatoire compris entre 600 et 900 s. Cet intervalle aléatoire est nécessaire afin de répartir la charge sur la source du dictionnaire lors des mises à jour sur un grand nombre de serveurs. Pendant les mises à jour, l’ancienne version d’un dictionnaire peut toujours être interrogée ; seul le chargement initial bloque les requêtes. Notez que définir (LIFETIME(0)) empêche la mise à jour des dictionnaires.
Les dictionnaires peuvent être rechargés de force à l’aide de la commande SYSTEM RELOAD DICTIONARY.
Pour les sources de base de données telles que ClickHouse et Postgres, vous pouvez configurer une requête qui mettra à jour les dictionnaires uniquement s’ils ont réellement changé (c’est la réponse de la requête qui le détermine), plutôt qu’à intervalles périodiques. Vous trouverez plus de détails ici.
Autres types de dictionnaires
Pour aller plus loin
- Bonnes pratiques pour les dictionnaires — choix du layout, dictionnaires ou JOIN, supervision
- Utiliser les dictionnaires pour accélérer les requêtes
- Configuration avancée des dictionnaires