Il n’est pas recommandé d’envoyer de nombreux petits batches en mode synchrone, car cela entraîne la création d’un grand nombre de parts. Cela dégrade les performances des queries et peut provoquer des erreurs “too many part”.
async_insert.
Les insertions asynchrones sont prises en charge à la fois par les interfaces HTTP et native TCP.
Lorsqu’elles sont activées (async_insert = 1), les insertions sont mises en tampon et écrites sur disk uniquement lorsqu’une des conditions de flush suivantes est remplie :
- Le tampon atteint une taille de données spécifiée (
async_insert_max_data_size, 100 MiB par défaut). - Un seuil de temps est atteint (
async_insert_busy_timeout_ms, 200 ms par défaut ou 1000 ms sur Cloud). - Un nombre maximal de queries d’insertion s’accumule (
async_insert_max_query_number, 450 par défaut).
Choisir un mode de retour
wait_for_async_insert.
Lorsqu’il est défini sur 1 (valeur par défaut), ClickHouse n’accuse réception de l’insert qu’une fois les données correctement écrites sur le disque. Cela garantit une forte durabilité et simplifie le traitement des erreurs : si un problème survient pendant le flush, l’erreur est renvoyée au client. Ce mode est recommandé dans la plupart des scénarios de production, en particulier lorsque les échecs d’insert doivent être suivis de manière fiable.
Les benchmarks montrent qu’il passe bien à l’échelle avec une forte concurrency — que vous exécutiez 200 ou 500 clients — grâce aux inserts adaptatifs et à un comportement stable lors de la création des parts.
Définir wait_for_async_insert = 0 active le mode « fire-and-forget ». Dans ce cas, le serveur accuse réception de l’insert dès que les données sont placées dans le tampon, sans attendre qu’elles soient écrites dans le stockage.
Cela permet des inserts à très faible latence et un throughput maximal, idéal pour des données à haut débit et à faible criticité. Cependant, cela implique des compromis : rien ne garantit que les données seront persistées, les erreurs n’apparaissent qu’au moment du flush, et il n’existe pas de dead-letter queue pour les inserts en échec — pour analyser les échecs, il faut inspecter les server logs et les system tables a posteriori. Utilisez ce mode uniquement si votre workload peut tolérer une perte de données.
Les benchmarks montrent également une réduction substantielle du nombre de parts et une baisse de l’utilisation CPU lorsque les flushes du tampon sont peu fréquents (par exemple, toutes les 30 secondes), mais le risque d’échec silencieux demeure.
Nous recommandons vivement d’utiliser async_insert=1,wait_for_async_insert=1 si vous utilisez des insertions asynchrones. Utiliser wait_for_async_insert=0 est très risqué, car votre client INSERT peut ne pas être informé en cas d’erreur. Cela peut également entraîner une surcharge si votre client continue à écrire rapidement alors que le ClickHouse server doit ralentir les écritures et appliquer une certaine contre-pression afin de garantir la fiabilité du service.
Insertions asynchrones adaptatives
async_insert_use_adaptive_busy_timeout). Au lieu d’un intervalle de flush fixe, le timeout s’ajuste dynamiquement entre un minimum (async_insert_busy_timeout_min_ms, 50 ms par défaut) et un maximum (async_insert_busy_timeout_max_ms, 200 ms par défaut ou 1000 ms sur Cloud) en fonction du débit des données entrantes.
Lorsque les données arrivent fréquemment, le timeout reste proche du minimum afin de déclencher le flush plus rapidement et de réduire la latence de bout en bout. Lorsque les données sont clairsemées, il se rapproche du maximum pour accumuler des lots plus volumineux. Cela est particulièrement utile dans le mode par défaut (wait_for_async_insert=1), où un timeout fixe élevé obligerait les clients à attendre pendant tout l’intervalle, même lorsque les données sont déjà prêtes à être écrites.
Gestion des erreurs
wait_for_async_insert=1), l’erreur est renvoyée au client. En mode fire-and-forget, les erreurs sont consignées dans les journaux du serveur et dans la table system.asynchronous_inserts.
Chaque flush crée au moins une part par valeur distincte de clé de partitionnement dans le tampon. Même pour les tables sans clé de partitionnement, un seul flush peut produire plusieurs parts si les données mises en tampon dépassent max_insert_block_size (environ 1 million de lignes par défaut).
Même avec les insertions asynchrones, vous pouvez toujours rencontrer des erreurs “too many parts” si la clé de partitionnement présente une cardinalité élevée.
Déduplication et fiabilité
Activation des insertions asynchrones
-
Activation des insertions asynchrones au niveau de l’utilisateur. Cet exemple utilise l’utilisateur
default; si vous créez un autre utilisateur, remplacez-le par ce nom d’utilisateur : -
Vous pouvez spécifier les paramètres d’insertion asynchrone à l’aide de la clause SETTINGS dans les requêtes d’insertion :
-
Vous pouvez également définir les paramètres d’insertion asynchrone comme paramètres de connexion lorsque vous utilisez un client ClickHouse pour un langage de programmation.
Par exemple, voici comment procéder dans une chaîne de connexion JDBC lorsque vous utilisez le pilote JDBC Java de ClickHouse pour vous connecter à ClickHouse Cloud :
Les insertions asynchrones ne s’appliquent pas aux requêtes
INSERT INTO ... SELECT. Lorsqu’une insertion contient une clause SELECT, la requête est toujours exécutée de manière synchrone, quel que soit le paramètre async_insert.Flush des tampons à l’arrêt
async insert en attente — par exemple, lors d’un arrêt propre ou avant une opération de maintenance — exécutez :
Comparaison avec les tables Buffer
- Aucune modification DDL n’est requise. Les insertions asynchrones sont transparentes : vous activez un paramètre, sans créer de tables supplémentaires.
- Mise en tampon par forme de requête. Les insertions asynchrones conservent des tampons distincts pour chaque combinaison unique de forme de requête et de paramètres, ce qui permet des politiques de flush granulaires. Les tables Buffer utilisent un seul tampon par table cible.
- Durabilité. Dans le mode par défaut (
wait_for_async_insert=1), les données sont confirmées sur disque avant que le client ne reçoive la confirmation. Les tables Buffer fonctionnent en mode fire-and-forget : les données mises en tampon sont perdues en cas de crash. - Comportement du cluster. Dans les clusters, les tampons d’insertion asynchrone sont maintenus par nœud. Les tables Buffer nécessitent une création explicite sur chaque nœud.