> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-detect-table-modification.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Déduplication des insertions lors des tentatives

> Éviter les doublons de données lors des nouvelles tentatives d’insertion

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](#settings-that-control-insert-deduplication).

<div id="limitations">
  ## Limites
</div>

<div id="uncertain-insert-status">
  ### Statut d'insertion incertain
</div>

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.

<div id="deduplication-window-limit">
  ### Limite de la fenêtre de déduplication
</div>

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.

<div id="settings-that-control-insert-deduplication">
  ## Paramètres contrôlant la déduplication des insertions
</div>

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.

<div id="insert-deduplication-for-tables">
  ### Paramètres au niveau de la table
</div>

**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`](/fr/reference/settings/merge-tree-settings/replicated-deduplication-window#replicated_deduplication_window) et [`replicated_deduplication_window_seconds`](/fr/reference/settings/merge-tree-settings/replicated-deduplication-window#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`](/fr/reference/settings/merge-tree-settings/other#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).

<Note>
  [`replicated_deduplication_window_for_async_inserts`](/fr/reference/settings/merge-tree-settings/replicated-deduplication-window#replicated_deduplication_window_for_async_inserts) et [`replicated_deduplication_window_seconds_for_async_inserts`](/fr/reference/settings/merge-tree-settings/replicated-deduplication-window#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.
</Note>

<div id="query-level-insert-deduplication">
  ### Paramètres au niveau de la requête
</div>

| Paramètre                                                                                                                                                | S’applique à                                | Par défaut             | Objectif                                                                                     |
| -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------- | -------------------------------------------------------------------------------------------- |
| [`deduplicate_insert`](/fr/reference/settings/session-settings/deduplicate-insert#deduplicate_insert)                                                    | Chaque `INSERT`, synchrone ou asynchrone    | `enable`               | Commutateur principal de la déduplication des insertions                                     |
| [`deduplicate_insert_select`](/fr/reference/settings/session-settings/deduplicate-insert#deduplicate_insert_select)                                      | `INSERT ... SELECT`                         | `enable_when_possible` | Détermine quoi faire lorsque le résultat de `SELECT` n’est pas reproductible                 |
| [`insert_deduplication_token`](/fr/reference/settings/session-settings/insert#insert_deduplication_token)                                                | Chaque `INSERT`                             | `''`                   | Identifie l’insertion à l’aide d’une chaîne fournie par l’utilisateur plutôt que des données |
| [`deduplicate_blocks_in_dependent_materialized_views`](/fr/reference/settings/session-settings/other#deduplicate_blocks_in_dependent_materialized_views) | Tables sous-jacentes aux vues matérialisées | `1`                    | Étend la déduplication aux destinations des vues matérialisées dépendantes                   |

`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.

<div id="precedence">
  ### Préséance
</div>

1. Pour une requête `INSERT ... SELECT`, c'est `deduplicate_insert_select` qui prévaut. Consultez [Déduplication pour INSERT ... SELECT](#deduplication-for-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`.

<div id="legacy-and-obsolete-settings">
  ### Paramètres legacy et obsolètes
</div>

| Paramètre                                                                                                   | Statut                                                                          | Utiliser à la place         |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | --------------------------- |
| [`insert_deduplicate`](/fr/reference/settings/session-settings/insert#insert_deduplicate)                   | Legacy. Lu uniquement lorsque `deduplicate_insert = backward_compatible_choice` | `deduplicate_insert`        |
| [`async_insert_deduplicate`](/fr/reference/settings/session-settings/async-insert#async_insert_deduplicate) | Legacy. Lu uniquement lorsque `deduplicate_insert = backward_compatible_choice` | `deduplicate_insert`        |
| `insert_select_deduplicate`                                                                                 | Obsolète. Sans effet                                                            | `deduplicate_insert_select` |
| `update_insert_deduplication_token_in_dependent_materialized_views`                                         | Obsolète. Sans effet                                                            | —                           |

<Warning>
  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`.
</Warning>

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`](/fr/reference/settings/session-settings/compatibility#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`.

<div id="how-insert-deduplication-works">
  ## Fonctionnement de la déduplication des insertions
</div>

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.

<div id="deduplication-for-insert-select">
  ## Déduplication des `INSERT ... SELECT`
</div>

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 :

| Valeur                              | Comportement                                                                                                                                                                                                                       |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enable_when_possible` (par défaut) | Déduplique lorsque le `SELECT` est stable ou qu'un jeton est défini. Sinon, ignore la déduplication et écrit un message dans le journal du serveur.                                                                                |
| `force_enable`                      | Déduplique toujours. Si le `SELECT` n'est pas stable et qu'aucun jeton n'est défini, lève l'exception `DEDUPLICATION_IS_NOT_POSSIBLE`.                                                                                             |
| `enable_even_for_bad_queries`       | Déduplique indépendamment de la stabilité. Conservé pour assurer la compatibilité descendante. Avec un `SELECT` instable, la nouvelle tentative n'est généralement pas reconnue comme un doublon ; préférez donc une autre valeur. |
| `disable`                           | Ne déduplique jamais `INSERT ... SELECT`.                                                                                                                                                                                          |

`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.

<div id="deduplication-for-asynchronous-inserts">
  ## Déduplication des insertions asynchrones
</div>

Les insertions asynchrones ([`async_insert`](/fr/reference/settings/session-settings/async-insert#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.

<Note>
  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`.
</Note>

<div id="asynchronous-insert-deduplication-granularity">
  ### Granularité de la déduplication
</div>

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`](/fr/reference/system-tables/events) comptabilisent ces deux cas.

<div id="asynchronous-inserts-and-materialized-views">
  ### Insertions asynchrones et vues matérialisées
</div>

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`](/fr/reference/settings/session-settings/max#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.

<div id="insert-deduplication-with-materialized-views">
  ## Déduplication des insertions avec les vues matérialisées
</div>

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 :

* [`replicated_deduplication_window`](/fr/reference/settings/merge-tree-settings/replicated-deduplication-window#replicated_deduplication_window)
* [`replicated_deduplication_window_seconds`](/fr/reference/settings/merge-tree-settings/replicated-deduplication-window#replicated_deduplication_window_seconds)
* [`non_replicated_deduplication_window`](/fr/reference/settings/merge-tree-settings/other#non_replicated_deduplication_window)

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`](/fr/reference/settings/session-settings/other#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.

<div id="examples">
  ## Exemples
</div>

<div id="identical-blocks-after-materialized-view-transformations">
  ### Blocs identiques après transformation dans une vue matérialisée
</div>

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 :

```sql theme={null}
CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE MATERIALIZED VIEW mv_dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000
AS SELECT
    0 AS key,
    value AS value
FROM dst;
```

```sql theme={null}
SET max_block_size=1;
SET min_insert_block_size_rows=0;
SET min_insert_block_size_bytes=0;
```

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 :

```sql theme={null}
SET deduplicate_blocks_in_dependent_materialized_views=1;
```

```sql theme={null}
INSERT INTO dst SELECT
    number + 1 AS key,
    IF(key = 0, 'A', 'B') AS value
FROM numbers(2);

SELECT
    *,
    _part
FROM dst
ORDER BY all;
```

```response theme={null}
┌─key─┬─value─┬─_part─────┐
│   1 │ B     │ all_0_0_0 │
│   2 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘
```

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.

```sql theme={null}
SELECT
    *,
    _part
FROM mv_dst
ORDER BY all;
```

```response theme={null}
┌─key─┬─value─┬─_part─────┐
│   0 │ B     │ all_0_0_0 │
│   0 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘
```

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.

```sql theme={null}
INSERT INTO dst SELECT
    number + 1 AS key,
    IF(key = 0, 'A', 'B') AS value
FROM numbers(2);

SELECT
    *,
    _part
FROM dst
ORDER BY all;
```

```response theme={null}
┌─key─┬─value─┬─_part─────┐
│   1 │ B     │ all_0_0_0 │
│   2 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘
```

```sql theme={null}
SELECT
    *,
    _part
FROM mv_dst
ORDER by all;
```

```response theme={null}
┌─key─┬─value─┬─_part─────┐
│   0 │ B     │ all_0_0_0 │
│   0 │ B     │ all_1_1_0 │
└─────┴───────┴───────────┘
```

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`.

<div id="identical-blocks-on-insertion">
  ### Blocs identiques à l’insertion
</div>

```sql theme={null}
CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

SET max_block_size=1;
SET min_insert_block_size_rows=0;
SET min_insert_block_size_bytes=0;
```

Insertion :

```sql theme={null}
INSERT INTO dst SELECT
    0 AS key,
    'A' AS value
FROM numbers(2);

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘
```

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 :

<div id="identical-blocks-in-insertion-with-insert_deduplication_token">
  ### Blocs identiques à l’insertion avec `insert_deduplication_token`
</div>

```sql theme={null}
CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

SET max_block_size=1;
SET min_insert_block_size_rows=0;
SET min_insert_block_size_bytes=0;
```

Insertion :

```sql theme={null}
INSERT INTO dst SELECT
    0 AS key,
    'A' AS value
FROM numbers(2)
SETTINGS insert_deduplication_token='some_user_token';

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_2_2_0 │
│ from dst   │   0 │ A     │ all_3_3_0 │
└────────────┴─────┴───────┴───────────┘
```

Deux blocs identiques ont bien été insérés, comme prévu.

```sql theme={null}
SELECT 'second attempt';

INSERT INTO dst SELECT
    0 AS key,
    'A' AS value
FROM numbers(2)
SETTINGS insert_deduplication_token='some_user_token';

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_2_2_0 │
│ from dst   │   0 │ A     │ all_3_3_0 │
└────────────┴─────┴───────┴───────────┘
```

La nouvelle tentative d’insertion est dédupliquée comme prévu.

```sql theme={null}
SELECT 'third attempt';

INSERT INTO dst SELECT
    1 AS key,
    'b' AS value
FROM numbers(2)
SETTINGS insert_deduplication_token='some_user_token';

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   0 │ A     │ all_2_2_0 │
│ from dst   │   0 │ A     │ all_3_3_0 │
└────────────┴─────┴───────┴───────────┘
```

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.

<div id="different-insert-operations-generate-the-same-data-after-transformation-in-the-underlying-table-of-the-materialized-view">
  ### 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
</div>

```sql theme={null}
CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE MATERIALIZED VIEW mv_dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000
AS SELECT
    0 AS key,
    value AS value
FROM dst;

SET deduplicate_blocks_in_dependent_materialized_views=1;

select 'first attempt';

INSERT INTO dst VALUES (1, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER by all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘
```

```sql theme={null}
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
```

```response theme={null}
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
└───────────────┴─────┴───────┴───────────┘
```

```sql theme={null}
select 'second attempt';

INSERT INTO dst VALUES (2, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER by all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
│ from dst   │   2 │ A     │ all_1_1_0 │
└────────────┴─────┴───────┴───────────┘
```

```sql theme={null}
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
```

```response theme={null}
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
│ from mv_dst   │   0 │ A     │ all_1_1_0 │
└───────────────┴─────┴───────┴───────────┘
```

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.

<div id="different-materialized-view-inserts-into-one-underlying-table-with-equivalent-data">
  ### Insertions depuis différentes vues matérialisées dans une même table sous-jacente avec des données équivalentes
</div>

```sql theme={null}
CREATE TABLE dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE TABLE mv_dst
(
    `key` Int64,
    `value` String
)
ENGINE = MergeTree
ORDER BY tuple()
SETTINGS non_replicated_deduplication_window=1000;

CREATE MATERIALIZED VIEW mv_first
TO mv_dst
AS SELECT
    0 AS key,
    value AS value
FROM dst;

CREATE MATERIALIZED VIEW mv_second
TO mv_dst
AS SELECT
    0 AS key,
    value AS value
FROM dst;

SET deduplicate_blocks_in_dependent_materialized_views=1;

select 'first attempt';

INSERT INTO dst VALUES (1, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER by all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘
```

```sql theme={null}
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
```

```response theme={null}
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
│ from mv_dst   │   0 │ A     │ all_1_1_0 │
└───────────────┴─────┴───────┴───────────┘
```

Deux blocs identiques ont été insérés dans la table `mv_dst` (comme prévu).

```sql theme={null}
SELECT 'second attempt';

INSERT INTO dst VALUES (1, 'A');

SELECT
    'from dst',
    *,
    _part
FROM dst
ORDER BY all;
```

```response theme={null}
┌─'from dst'─┬─key─┬─value─┬─_part─────┐
│ from dst   │   1 │ A     │ all_0_0_0 │
└────────────┴─────┴───────┴───────────┘
```

```sql theme={null}
SELECT
    'from mv_dst',
    *,
    _part
FROM mv_dst
ORDER by all;
```

```response theme={null}
┌─'from mv_dst'─┬─key─┬─value─┬─_part─────┐
│ from mv_dst   │   0 │ A     │ all_0_0_0 │
│ from mv_dst   │   0 │ A     │ all_1_1_0 │
└───────────────┴─────┴───────┴───────────┘
```

Cette tentative est dédupliquée dans les deux tables `dst` et `mv_dst`.
