Skip to main content
Le type de colonne JSON est prêt pour la production à partir de ClickHouse 25.3+. Les versions antérieures ne sont pas recommandées pour une utilisation en production.
Vos données arrivent en JSON. ClickHouse vous propose plusieurs façons de les stocker, depuis des colonnes entièrement typées jusqu’à un String brut. Le bon choix dépend du degré de prévisibilité de votre schéma et de la nécessité d’effectuer des requêtes sur des champs individuels. Portée : Cette page traite des choix de conception du schéma pour stocker des données JSON. Elle ne couvre pas les formats JSON d’entrée/sortie, les fonctions JSON, ni la syntaxe des requêtes. Pour plus d’informations sur le type de colonne JSON lui-même, consultez Use JSON where appropriate. Prérequis : Connaissance de la création de tables ClickHouse, des bases de MergeTree et de la syntaxe des types de colonnes.

Décision rapide

  • Si chaque champ a un type connu et stable, et que le schéma évolue rarement Colonnes typées
  • Si la plupart des champs sont stables, mais qu’une partie est dynamique ou imprévisible Hybride (typé + JSON)
  • Si toute la structure est dynamique, avec des clés qui apparaissent et disparaissent d’un enregistrement à l’autre Colonne JSON native
  • Si les champs dynamiques sont des paires clé-valeur avec un type de valeur uniforme (par ex. des tags sous forme de chaînes ou des métriques numériques) Map plutôt que JSON
  • Si vous vous contentez de stocker et de récupérer le blob JSON, sans requêtes au niveau des champs Stockage opaque en String
Ne confondez pas le format JSON avec le type de colonne JSON. Vous pouvez insérer des données au format JSON (via JSONEachRow, etc.) dans des colonnes typées sans utiliser du tout le type de colonne JSON. Ici, il s’agit de choisir des types de colonnes, pas des formats d’entrée.

Détails de l’approche

Colonnes typées

Quand l’utiliser : La structure JSON est entièrement connue dès la conception. Les champs et les types ne changent pas d’un enregistrement à l’autre. Même des structures imbriquées complexes (tableaux d’objets, maps imbriquées) peuvent être représentées avec les types Array, Tuple et Nested. Compromis : Les changements de schéma nécessitent ALTER TABLE. Les champs inattendus sont silencieusement ignorés à l’insertion, sauf si le schéma est mis à jour.
Mise en place
Vérification
Points d’attention
  • Si vous insérez des données JSON avec JSONEachRow et que le JSON contient des champs absents du schéma, ClickHouse les ignore silencieusement par défaut. Définissez input_format_skip_unknown_fields sur 0 si vous préférez obtenir des erreurs.

Hybride (colonnes typées + JSON)

Quand l’utiliser : Un ensemble de champs de base est stable (timestamp, ID, codes d’état), mais une partie du payload est dynamique. Pensez à des attributs définis par l’utilisateur, des tags, des métadonnées ou des champs d’extension qui varient d’un enregistrement à l’autre. Compromis : Performances maximales sur les colonnes typées, flexibilité sur la colonne JSON. La colonne JSON implique malgré tout une surcharge à l’insert et un coût de stockage pour sa partie dynamique.
Configuration
Vérification
Points d’attention
  • Utilisez des indications de type sur les chemins JSON que vous connaissez à l’avance. Elles contournent la colonne discriminante et stockent le chemin comme une colonne typée classique, avec les mêmes performances et sans surcharge.
  • Utilisez SKIP ou SKIP REGEXP pour les chemins que vous n’interrogez jamais (métadonnées de débogage, ID internes de tracing) afin d’économiser de l’espace de stockage et de réduire le nombre de sous-colonnes.
  • Définissez max_dynamic_paths en fonction du nombre de chemins distincts que vous interrogez réellement. La valeur par défaut (1024) convient dans la plupart des cas. Réduisez-la si votre section dynamique est limitée.
  • Ne définissez pas max_dynamic_paths au-delà de 10 000. Des valeurs élevées augmentent la consommation de ressources et réduisent l’efficacité.
Clés avec pointsLes clés contenant des points (par ex. http.status_code) sont traitées par défaut comme des chemins imbriqués ; ainsi, {"http.status_code": 200} est stocké de la même manière que {"http": {"status_code": 200}}. C’est courant avec les attributs OTel. Utilisez des indications de type pour contrôler la façon dont les chemins avec points sont stockés, ou activez json_type_escape_dots_in_keys (25.8+).

Colonne JSON native

Quand l’utiliser : La structure est véritablement imprévisible, avec des clés qui apparaissent et disparaissent d’un enregistrement à l’autre. Schémas générés par les utilisateurs, systèmes de plugins ou ingestion dans un lac de données lorsque vous ne contrôlez pas le schéma en amont. Compromis : Les insertions sont plus lentes qu’avec des colonnes typées. Les lectures de l’objet complet sont plus lentes qu’avec String. Surcoût de stockage lié à la gestion des sous-colonnes. Fonctionne bien pour les requêtes au niveau des champs sur des chemins spécifiques.
Configuration
Utilisez le format JSONAsObject lors de l’insertion de documents JSON complets dans une colonne JSON. Il traite chaque ligne d’entrée comme un objet JSON complet associé à la colonne.Vérification
Points d’attention
  • Sans indications de type, ClickHouse déduit les types chemin par chemin à partir des premières valeurs observées. Si score arrive sous la forme "10" (chaîne) dans un enregistrement et 10 (entier) dans un autre, le chemin reçoit une colonne discriminante et les requêtes deviennent plus lentes. Ajoutez des indications pour les chemins dont les types sont connus.
  • Lorsque le nombre de chemins dépasse max_dynamic_paths, les valeurs excédentaires sont déplacées vers une shared data structure, ce qui réduit les performances des requêtes. Surveillez cela avec JSONDynamicPaths() et maintenez la limite sous 10 000.
  • Chaque chemin dynamique prend en charge jusqu’à max_dynamic_types (32 par défaut) types de données distincts. Si un même chemin dépasse cette limite, les types supplémentaires basculent vers un stockage Variant partagé. Cela a rarement de l’importance, sauf si vos données présentent des types très incohérents pour un même champ.

Stockage opaque en String

Quand l’utiliser : les documents JSON sont stockés et récupérés en bloc, puis transmis à une application, archivés ou relayés en aval. Aucun filtrage ni aucune agrégation au niveau des champs dans ClickHouse. Compromis : insertions les plus rapides et schéma le plus simple. Pas de requêtes au niveau des champs sans analyse à l’exécution (famille JSONExtract), ce qui est lent à grande échelle.
Configuration
Vérification
Points de vigilance
  • Si les besoins évoluent et que vous devez ensuite effectuer des requêtes au niveau des champs, il vous faudra créer une nouvelle table avec des colonnes typées ou JSON, puis backfill les données. S’il y a la moindre chance que vous interrogiez des champs individuels, privilégiez plutôt l’approche hybride.
  • Les fonctions JSONExtract analysent la chaîne à chaque requête. C’est acceptable pour une exploration ad hoc, mais pas pour des dashboards de production ni pour des workloads à QPS élevé.
  • Envisagez des codecs de compression (ZSTD) sur la colonne String si les payloads JSON sont volumineux : la compression est efficace.

Comparaison

Quand Map convient mieux

Si vos champs dynamiques sont des paires clé-valeur homogènes — c’est-à-dire que toutes les valeurs ont le même type — Map(String, T) est plus simple et plus efficace qu’une colonne JSON. Exemples courants : des tags de type chaîne (Map(String, String)), des métriques numériques (Map(String, Float64)) ou des feature flags (Map(String, Bool)).
Map prend en charge le filtrage au niveau des clés (tags['env'] = 'prod'), coûte moins cher à stocker que JSON et évite la surcharge liée aux sous-colonnes du type JSON. Notez que, par défaut, les recherches de clés parcourent la map linéairement — cela convient pour de petits ensembles de tags, mais pour les maps de plus de 100 clés, envisagez la sérialisation with_buckets. Utilisez JSON lorsque les valeurs ont des types hétérogènes ou que la structure est imbriquée — utilisez Map lorsqu’il s’agit de paires clé-valeur simples avec un type de valeur uniforme.
Dernière modification le 23 juillet 2026