- À tout moment, votre table peut encore contenir des doublons (des lignes avec la même clé de tri)
- La suppression effective des lignes en double se produit lors de la fusion des parts
- Vos requêtes doivent tenir compte de la possibilité de doublons
| ClickHouse propose une formation gratuite sur la déduplication et de nombreux autres sujets. Le Deleting and Updating Data training module constitue un bon point de départ. |
Options de déduplication
-
Moteur de table
ReplacingMergeTree: avec ce moteur de table, les lignes dupliquées ayant la même clé de tri sont supprimées lors des fusions.ReplacingMergeTreeest une bonne option pour simuler un comportement d’upsert (lorsque vous souhaitez que les requêtes renvoient la dernière ligne insérée). -
Collapsing de lignes : les moteurs de table
CollapsingMergeTreeetVersionedCollapsingMergeTreeutilisent une logique dans laquelle une ligne existante est « annulée » et une nouvelle ligne est insérée. Ils sont plus complexes à mettre en œuvre queReplacingMergeTree, mais vos requêtes et agrégations peuvent être plus simples à écrire, sans avoir à vous soucier de savoir si les données ont déjà été fusionnées ou non. Ces deux moteurs de table sont utiles lorsque vous devez mettre à jour fréquemment les données.
Utilisation de ReplacingMergeTree pour les upserts
views qui indique le nombre de fois qu’un commentaire a été consulté. Supposons que nous insérions une nouvelle ligne lorsqu’un article est publié, puis que nous effectuions chaque jour l’upsert d’une nouvelle ligne avec le nombre total de vues si cette valeur augmente :
views, insérez une nouvelle ligne avec la même clé primaire (notez les nouvelles valeurs de la colonne views) :
FINAL dans la requête SELECT, ce qui entraîne une fusion logique du résultat de la requête :
Utiliser
FINAL fonctionne bien si vous avez peu de données. Si vous traitez un grand volume de données,
FINAL n’est probablement pas la meilleure option. Voyons une meilleure solution pour
trouver la dernière valeur d’une colonne.Éviter FINAL
views pour les deux lignes distinctes :
FINAL).
FINAL, appuyons-nous sur une logique métier : nous savons que la colonne views augmente toujours. Nous pouvons donc sélectionner la ligne dont la valeur est la plus élevée à l’aide de la fonction max, après regroupement selon les colonnes souhaitées :
FINAL.
Notre module de formation Deleting and Updating Data approfondit cet exemple, notamment en expliquant comment utiliser une colonne version avec ReplacingMergeTree.
Utiliser CollapsingMergeTree pour mettre à jour fréquemment des colonnes
ALTER TABLE..UPDATE et d’insérer simplement les nouvelles données en plus des données existantes. On pourrait ajouter une colonne indiquant si les données sont obsolètes ou nouvelles… et il existe justement déjà un moteur de table qui implémente ce comportement de façon très élégante, d’autant plus qu’il supprime automatiquement les données obsolètes à votre place. Voyons comment cela fonctionne.
Supposons que nous suivions le nombre de consultations d’un commentaire Hacker News à l’aide d’un système externe et que, toutes les quelques heures, nous envoyions les données dans ClickHouse. Nous voulons que les anciennes lignes soient supprimées et que les nouvelles lignes représentent le nouvel état de chaque commentaire Hacker News. Nous pouvons utiliser un CollapsingMergeTree pour implémenter ce comportement.
Définissons une table pour stocker le nombre de consultations :
hackernews_views comporte une colonne Int8 nommée sign, appelée colonne sign. Le nom de la colonne sign est arbitraire, mais le type de données Int8 est obligatoire, et notez que le nom de la colonne a été passé au constructeur de la table CollapsingMergeTree.
Qu’est-ce que la colonne sign d’une table CollapsingMergeTree ? Elle représente l’état de la ligne, et la colonne sign ne peut prendre que les valeurs 1 ou -1. Voici comment cela fonctionne :
- Si deux lignes ont la même clé primaire (ou le même ordre de tri s’il diffère de la clé primaire), mais des valeurs différentes dans la colonne sign, alors la dernière ligne insérée avec un +1 devient la ligne d’état et les autres lignes s’annulent mutuellement
- Les lignes qui s’annulent mutuellement sont supprimées lors des fusions
- Les lignes qui n’ont pas de paire correspondante sont conservées
hackernews_views. Comme il s’agit de la seule ligne pour cette clé primaire, nous définissons son état sur 1 :
views. Vous insérez deux lignes : l’une pour annuler la ligne existante, et l’autre contenant le nouvel état de la ligne :
(123, 'ricardo') :
FINAL renvoie la ligne d’état actuelle :
FINAL n’est pas recommandée pour les tables volumineuses.
La valeur fournie pour la colonne
views dans notre exemple n’est pas vraiment nécessaire, et elle n’a pas non plus besoin de correspondre à la valeur actuelle de views dans l’ancienne ligne. En fait, vous pouvez annuler une ligne avec uniquement la clé primaire et un -1 :Mises à jour en temps réel depuis plusieurs threads
CollapsingMergeTree, les lignes s’annulent entre elles à l’aide d’une colonne sign, et l’état d’une ligne est déterminé par la dernière ligne insérée. Mais cela peut poser problème si vous insérez des lignes depuis différents threads, car elles peuvent être insérées dans le désordre. Dans ce cas, utiliser la « dernière » ligne ne fonctionne pas.
C’est là que VersionedCollapsingMergeTree devient utile : il regroupe les lignes comme CollapsingMergeTree, mais au lieu de conserver la dernière ligne insérée, il garde celle dont la valeur dans la colonne de version que vous spécifiez est la plus élevée.
Prenons un exemple. Supposons que nous voulions suivre le nombre de vues de nos commentaires Hacker News et que les données soient mises à jour fréquemment. Nous voulons que les rapports utilisent les valeurs les plus récentes sans devoir forcer ni attendre les fusions. Nous commençons avec une table similaire à CollapsedMergeTree, sauf que nous ajoutons une colonne pour stocker la version de l’état de la ligne :
VersionsedCollapsingMergeTree comme moteur et prend en paramètre la colonne sign et une colonne de version. Voici comment elle fonctionne :
- Elle supprime chaque paire de lignes ayant la même clé primaire et la même version, mais un signe différent
- L’ordre dans lequel les lignes ont été insérées n’a pas d’importance
- Notez que si la colonne de version ne fait pas partie de la clé primaire, ClickHouse l’ajoute implicitement à la clé primaire comme dernier champ
hackernews_views_vcmt :
VersionedCollapsingMergeTree est très pratique lorsque vous souhaitez mettre en œuvre la déduplication lors de l’insertion de lignes depuis plusieurs clients et/ou threads.
Pourquoi mes lignes ne sont-elles pas dédupliquées ?
INSERT. Par exemple, si vous insérez des lignes avec la colonne createdAt DateTime64(3) DEFAULT now(), vos lignes seront forcément uniques, car chaque ligne aura une valeur par défaut différente pour la colonne createdAt. Le moteur de table MergeTree / ReplicatedMergeTree ne pourra donc pas dédupliquer ces lignes, puisque chaque ligne insérée générera une somme de contrôle unique.
Dans ce cas, vous pouvez définir votre propre insert_deduplication_token pour chaque lot de lignes afin de garantir que plusieurs insertions du même lot n’entraînent pas la réinsertion des mêmes lignes. Consultez la documentation sur insert_deduplication_token pour plus de détails sur l’utilisation de ce paramètre.