Skip to main content
Les opérations d’insertion peuvent parfois échouer en raison d’erreurs, comme des expirations de délai. Lorsqu’une insertion échoue, il est possible que les données aient été insérées avec succès, ou non. Ce guide explique le fonctionnement de la déduplication lors des nouvelles tentatives d’insertion, afin d’éviter que les mêmes données soient insérées plus d’une fois. Lorsqu’une insertion est relancée, ClickHouse essaie de déterminer si les données ont déjà été insérées avec succès. Si les données insérées sont marquées comme doublons, ClickHouse ne les insère pas dans la table de destination. Toutefois, l’utilisateur recevra tout de même un statut de réussite, comme si les données avaient été insérées normalement. La déduplication couvre les insertions synchrones, les insertions asynchrones et les requêtes INSERT ... SELECT. Un paramètre, deduplicate_insert, contrôle les insertions synchrones et asynchrones. INSERT ... SELECT nécessite une attention particulière et dispose de son propre paramètre. Consultez les paramètres qui contrôlent la déduplication des insertions.

Limites

Statut d’insertion incertain

L’utilisateur doit réessayer l’opération d’insertion jusqu’à ce qu’elle réussisse. Si toutes les nouvelles tentatives échouent, il est impossible de déterminer si les données ont été insérées ou non. Lorsque des vues matérialisées sont impliquées, il est également impossible de savoir dans quelles tables les données ont pu apparaître. Les vues matérialisées peuvent être désynchronisées par rapport à la table source.

Limite de la fenêtre de déduplication

Si plus de *_deduplication_window autres opérations d’insertion ont lieu pendant la séquence de nouvelles tentatives, la déduplication risque de ne pas fonctionner comme prévu. Dans ce cas, les mêmes données peuvent être insérées plusieurs fois.

Paramètres contrôlant la déduplication des insertions

ClickHouse déduplique une insertion uniquement lorsque les deux conditions suivantes sont réunies :
  1. La table de destination conserve un journal de déduplication. Il s’agit d’un paramètre défini au niveau de la table.
  2. La déduplication est activée pour la requête. Il s’agit d’un paramètre défini au niveau de la requête.

Paramètres au niveau de la table

Seuls les moteurs *MergeTree prennent en charge la déduplication à l’insertion. Pour les moteurs *ReplicatedMergeTree, le journal de déduplication est activé par défaut et contrôlé par les paramètres replicated_deduplication_window et replicated_deduplication_window_seconds. Pour les moteurs *MergeTree non répliqués, le journal est contrôlé par le paramètre non_replicated_deduplication_window, qui vaut 0 par défaut. Une table MergeTree simple ne déduplique donc rien tant que vous ne définissez pas cette fenêtre sur une valeur positive. Les paramètres ci-dessus définissent la configuration du journal de déduplication d’une table. Le journal de déduplication stocke un nombre fini de block_id, qui déterminent le fonctionnement de la déduplication (voir ci-dessous).
replicated_deduplication_window_for_async_inserts et replicated_deduplication_window_seconds_for_async_inserts sont des paramètres legacy. Les insertions synchrones et asynchrones partagent désormais un même journal de déduplication, de sorte que replicated_deduplication_window régit les deux. Les paramètres legacy limitaient uniquement l’ancien répertoire ClickHouse Keeper, ce qui est important lors d’une mise à niveau progressive.

Paramètres au niveau de la requête

deduplicate_insert accepte trois valeurs :
  • enable — la déduplication est activée pour la requête INSERT.
  • disable — la déduplication est désactivée pour la requête INSERT.
  • backward_compatible_choice — la décision est déléguée aux paramètres legacy insert_deduplicate (insertions synchrones) et async_insert_deduplicate (insertions asynchrones).
Notez qu’une requête exécutée avec deduplicate_insert = disable n’écrit aucun block_id pour ses blocs. Ces données ne peuvent pas être dédupliquées ultérieurement, même si vous réessayez l’insertion avec deduplicate_insert = enable. Il en va de même lorsque la table de destination ne conserve aucun journal de déduplication : rien n’est enregistré, donc rien ne peut être comparé lors d’une nouvelle tentative.

Préséance

  1. Pour une requête INSERT ... SELECT, c’est deduplicate_insert_select qui prévaut. Consultez Déduplication pour INSERT … SELECT.
  2. Pour tout autre INSERT, c’est deduplicate_insert qui prévaut.
  3. insert_deduplicate et async_insert_deduplicate ne sont lus que lorsque deduplicate_insert vaut backward_compatible_choice.

Paramètres legacy et obsolètes

Depuis la version 26.2, deduplicate_insert a pour valeur par défaut enable. Par conséquent, définir insert_deduplicate = 0 ne suffit plus à désactiver la déduplication. Pour désactiver la déduplication, définissez deduplicate_insert = disable.
La version 26.2 a également modifié les valeurs par défaut de async_insert et de deduplicate_blocks_in_dependent_materialized_views, qui sont désormais activés. Le paramètre compatibility régit ces trois paramètres. Si vous définissez compatibility sur une version antérieure à 26.2, ces paramètres conservent leurs anciennes valeurs par défaut : deduplicate_insert devient backward_compatible_choice, ce qui laisse la décision à insert_deduplicate et async_insert_deduplicate. Un paramètre explicitement affecté est toujours respecté et n’est jamais affecté par compatibility.

Fonctionnement de la déduplication des insertions

Lorsque des données sont insérées dans ClickHouse, celui-ci les découpe en blocs selon le nombre de lignes et d’octets. Pour les tables utilisant des moteurs *MergeTree, chaque bloc se voit attribuer un block_id unique, qui est un hash des données de ce bloc. Ce block_id est utilisé comme clé unique pour l’opération d’insertion. Si le même block_id est trouvé dans le journal de déduplication, le bloc est considéré comme un doublon et n’est pas inséré dans la table. Cette approche fonctionne bien lorsque les insertions contiennent des données différentes. En revanche, si les mêmes données sont insérées intentionnellement plusieurs fois, vous devez utiliser le paramètre insert_deduplication_token pour contrôler le processus de déduplication. Ce paramètre vous permet de spécifier un jeton unique pour chaque insertion, que ClickHouse utilise pour déterminer si les données constituent un doublon. insert_deduplication_token a une priorité plus élevée : ClickHouse n’utilise pas le hash des données lorsqu’un jeton est fourni. Pour les requêtes INSERT ... VALUES, le découpage des données insérées en blocs est déterministe et dépend des paramètres. Vous devez donc relancer les insertions avec les mêmes valeurs de paramètres que lors de l’opération initiale.

Déduplication des INSERT ... SELECT

Pour les requêtes INSERT ... SELECT, la partie SELECT doit renvoyer les mêmes données dans le même ordre à chaque tentative. Sinon, les blocs diffèrent, les block_id diffèrent et la nouvelle tentative n’est pas reconnue comme un doublon. ClickHouse ne peut pas vérifier que les données sources n’ont pas changé, mais il peut déterminer si la requête produit elle-même un résultat reproductible. Un SELECT est considéré comme stable lorsque les deux conditions suivantes sont remplies :
  • La requête contient une clause ORDER BY ALL. Seul le littéral ORDER BY ALL est reconnu. Un simple ORDER BY <expressions> ne l’est pas, et une UNION de deux SELECT ou plus n’est jamais stable.
  • Le pipeline de lecture se termine par un seul flux.
Un insert_deduplication_token non vide constitue une alternative équivalente à la stabilité, car c’est alors le jeton, et non les données, qui identifie l’insertion. Le paramètre deduplicate_insert_select définit le comportement à adopter : enable_when_possible et enable_even_for_bad_queries tiennent également compte de deduplicate_insert : s’il est défini sur disable, la requête n’est pas dédupliquée. force_enable surcharge deduplicate_insert. Gardez à l’esprit que la table sélectionnée peut être mise à jour entre deux tentatives. Les deux approches ont alors des effets opposés :
  • Sans insert_deduplication_token, les block_id sont calculés à partir des données. Le résultat modifié produit des block_id différents, la déduplication n’a pas lieu et la nouvelle tentative insère les nouvelles données en plus de celles déjà écrites lors de la première tentative.
  • Avec insert_deduplication_token, le jeton seul identifie l’insertion. La nouvelle tentative est reconnue comme un doublon et est ignorée, même si elle aurait inséré des données différentes.
Choisissez l’approche qui correspond au sens que vous souhaitez donner à une nouvelle tentative. Par ailleurs, lorsque vous insérez de grandes quantités de données, le nombre de blocs peut dépasser la fenêtre du journal de déduplication, et ClickHouse ne saura alors pas qu’il doit dédupliquer ces blocs.

Déduplication des insertions asynchrones

Les insertions asynchrones (async_insert, activées par défaut depuis la version 26.2) sont dédupliquées lors des tentatives ultérieures, de la même manière que les insertions synchrones. deduplicate_insert contrôle les deux ; aucun paramètre distinct n’est donc nécessaire. Les deux types d’insertion partagent également un même journal de déduplication et calculent les block_id de la même façon. Vous pouvez donc basculer un client entre les insertions synchrones et asynchrones sans compromettre la déduplication, et une nouvelle tentative envoyée dans un mode reste reconnue comme le doublon d’une tentative envoyée dans l’autre. Le passage d’une charge de travail des insertions synchrones aux insertions asynchrones reste sans risque pour une table qui repose sur la déduplication.
Avant la version 26.2, la déduplication des insertions asynchrones était désactivée par défaut et contrôlée par async_insert_deduplicate. Ce paramètre n’est désormais lu que lorsque deduplicate_insert est défini sur backward_compatible_choice.

Granularité de la déduplication

Le serveur regroupe plusieurs insertions asynchrones dans un même lot et écrit ce lot sous la forme d’une ou plusieurs parties, à raison d’au moins une par valeur distincte de clé de partition. La déduplication s’effectue par requête utilisateur, et non par lot :
  • Chaque requête en file d’attente apporte un jeton de déduplication au lot.
  • Un jeton correspond soit à la valeur de insert_deduplication_token, lorsque la requête en fournit une, soit à un hash des lignes apportées par cette requête.
  • Le regroupement en lots n’influence pas les jetons, et insert_deduplication_token n’influence pas la façon dont les requêtes sont regroupées en lots.
Cela a deux conséquences :
  • Lorsqu’une requête d’un lot est un doublon, ClickHouse ne supprime que les lignes de cette requête. Le reste du lot est inséré normalement. Une partie n’est entièrement ignorée que lorsque toutes ses lignes sont supprimées.
  • Lorsque deux requêtes du même lot portent le même jeton, la seconde est supprimée avant l’écriture de la partie. Cela s’applique par partition : si les deux requêtes écrivent des lignes dans des partitions différentes, elles sont toutes deux conservées.
Les événements DuplicatedAsyncInserts et SelfDuplicatedAsyncInserts de system.events comptabilisent ces deux cas.

Insertions asynchrones et vues matérialisées

La déduplication des insertions asynchrones fonctionne avec les vues matérialisées dépendantes. La règle est simple : un bloc en entrée, un bloc en sortie. Si la requête interne d’une vue transforme un bloc d’entrée en un bloc de sortie, la déduplication fonctionne. Si la vue émet un deuxième bloc, ClickHouse lève une exception NOT_IMPLEMENTED. Une vue émet un deuxième bloc lorsque sa sortie ne tient plus dans un seul bloc. max_block_size définit le nombre de lignes qu’un bloc peut contenir. Les transformations de colonnes, le filtrage et l’agrégation n’ajoutent jamais de lignes et restent donc toujours dans un seul bloc. Un JOIN peut ajouter des lignes. Il fonctionne tant que le résultat reste inférieur à max_block_size et échoue au-delà. Pour insérer des données via une vue qui émet plus d’un bloc, définissez deduplicate_blocks_in_dependent_materialized_views = 0 ou utilisez des insertions synchrones.

Déduplication des insertions avec les vues matérialisées

Lorsqu’une table possède une ou plusieurs vues matérialisées, les données insérées sont également insérées, avec les transformations définies, dans la destination de ces vues. Les données transformées sont elles aussi dédupliquées en cas de nouvelle tentative. ClickHouse effectue la déduplication pour les vues matérialisées de la même manière que pour les données insérées dans la table cible. Vous pouvez contrôler ce processus à l’aide des paramètres suivants pour la table source : La déduplication dans les tables sous-jacentes à des vues matérialisées est également régie par le paramètre de profil utilisateur deduplicate_blocks_in_dependent_materialized_views, qui est activé par défaut depuis la version 26.2. Les deux paramètres doivent l’autoriser : deduplicate_insert déduplique les données insérées dans la table source, et deduplicate_blocks_in_dependent_materialized_views déduplique également les données des tables dépendantes. Activez les deux si vous souhaitez une déduplication complète. Lors de l’insertion de blocs dans des tables sous-jacentes à des vues matérialisées, ClickHouse calcule le block_id en hachant une chaîne qui combine les block_id de la table source et des identifiants supplémentaires. Cela garantit une déduplication précise au sein des vues matérialisées, en permettant de distinguer les données selon leur insertion d’origine, indépendamment des transformations appliquées avant qu’elles n’atteignent la table de destination sous la vue matérialisée.

Exemples

Blocs identiques après transformation dans une vue matérialisée

Les blocs identiques générés lors d’une transformation dans une vue matérialisée ne sont pas dédupliqués, car ils reposent sur des données insérées différentes. Voici un exemple :
Les paramètres ci-dessus nous permettent d’effectuer une sélection sur une table contenant une série de blocs d’une seule ligne. Ces petits blocs ne sont pas fusionnés et restent inchangés jusqu’à leur insertion dans une table. Nous activons explicitement la déduplication dans la vue matérialisée, bien qu’elle soit activée par défaut :
Ici, on voit que deux parts ont été insérées dans la table dst. 2 blocs issus du select — 2 parts à l’insertion. Les parts contiennent des données différentes.
Ici, on voit que 2 parts ont été insérées dans la table mv_dst. Ces parts contiennent les mêmes données, mais elles ne sont pas dédupliquées.
Ici, on constate que lorsque nous réessayons les insertions, toutes les données sont dédupliquées. La déduplication fonctionne à la fois pour les tables dst et mv_dst.

Blocs identiques à l’insertion

Insertion :
Avec les paramètres ci-dessus, deux blocs résultent du select– il devrait donc y avoir deux blocs à insérer dans la table dst. Cependant, nous constatons qu’un seul bloc a été inséré dans la table dst. Cela s’explique par le fait que le deuxième bloc a été dédupliqué. Il contient les mêmes données ainsi que la clé de déduplication block_id, calculée comme un hash à partir des données insérées. Ce comportement n’est pas celui attendu. De tels cas sont rares, mais théoriquement possibles. Pour gérer correctement de tels cas, l’utilisateur doit fournir un insert_deduplication_token. Corrigeons cela avec les exemples suivants :

Blocs identiques à l’insertion avec insert_deduplication_token

Insertion :
Deux blocs identiques ont bien été insérés, comme prévu.
La nouvelle tentative d’insertion est dédupliquée comme prévu.
Cette insertion est également dédupliquée, même si elle contient des données insérées différentes. Notez que insert_deduplication_token est prioritaire : ClickHouse n’utilise pas l’empreinte de hachage des données lorsque insert_deduplication_token est fourni.

Différentes opérations d’insertion aboutissent aux mêmes données après transformation dans la table sous-jacente de la vue matérialisée

Nous insérons des données différentes à chaque fois. Cependant, les mêmes données sont insérées dans la table mv_dst. Les données ne sont pas dédupliquées, car les données source étaient différentes.

Insertions depuis différentes vues matérialisées dans une même table sous-jacente avec des données équivalentes

Deux blocs identiques ont été insérés dans la table mv_dst (comme prévu).
Cette tentative est dédupliquée dans les deux tables dst et mv_dst.
Dernière modification le 26 août 2026