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
Limite de la fenêtre de déduplication
*_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
- La table de destination conserve un journal de déduplication. Il s’agit d’un paramètre défini au niveau de la table.
- 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
*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êteINSERT.disable— la déduplication est désactivée pour la requêteINSERT.backward_compatible_choice— la décision est déléguée aux paramètres legacyinsert_deduplicate(insertions synchrones) etasync_insert_deduplicate(insertions asynchrones).
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
- Pour une requête
INSERT ... SELECT, c’estdeduplicate_insert_selectqui prévaut. Consultez Déduplication pour INSERT … SELECT. - Pour tout autre
INSERT, c’estdeduplicate_insertqui prévaut. insert_deduplicateetasync_insert_deduplicatene sont lus que lorsquededuplicate_insertvautbackward_compatible_choice.
Paramètres legacy et obsolètes
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
*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
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éralORDER BY ALLest reconnu. Un simpleORDER BY <expressions>ne l’est pas, et uneUNIONde deuxSELECTou plus n’est jamais stable. - Le pipeline de lecture se termine par un seul flux.
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, lesblock_idsont calculés à partir des données. Le résultat modifié produit desblock_iddiffé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.
Déduplication des 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
- 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_tokenn’influence pas la façon dont les requêtes sont regroupées en lots.
- 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.
DuplicatedAsyncInserts et SelfDuplicatedAsyncInserts de system.events comptabilisent ces deux cas.
Insertions asynchrones et vues matérialisées
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
replicated_deduplication_windowreplicated_deduplication_window_secondsnon_replicated_deduplication_window
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
dst. 2 blocs issus du select — 2 parts à l’insertion. Les parts contiennent des données différentes.
mv_dst. Ces parts contiennent les mêmes données, mais elles ne sont pas dédupliquées.
dst et mv_dst.
Blocs identiques à l’insertion
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
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
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
mv_dst (comme prévu).
dst et mv_dst.