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.
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)
→
Mapplutô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
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 et points d’attention
Mise en place, vérification et points d’attention
Mise en placeVérificationPoints d’attention
- Si vous insérez des données JSON avec
JSONEachRowet que le JSON contient des champs absents du schéma, ClickHouse les ignore silencieusement par défaut. Définissezinput_format_skip_unknown_fieldssur0si vous préférez obtenir des erreurs.
Hybride (colonnes typées + JSON)
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 et points d’attention
Configuration, vérification et points d’attention
ConfigurationVérificationPoints 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
SKIPouSKIP REGEXPpour 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_pathsen 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_pathsau-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
Configuration, vérification et points d’attention
Configuration, vérification et points d’attention
ConfigurationUtilisez le format Points d’attention
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- Sans indications de type, ClickHouse déduit les types chemin par chemin à partir des premières valeurs observées. Si
scorearrive sous la forme"10"(chaîne) dans un enregistrement et10(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 avecJSONDynamicPaths()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
JSONExtract), ce qui est lent à grande échelle.
Configuration, vérification et pièges à éviter
Configuration, vérification et pièges à éviter
ConfigurationVérificationPoints 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
JSONExtractanalysent 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
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.
- Utiliser JSON lorsque c’est pertinent — quand utiliser le type de colonne JSON plutôt que d’autres solutions
- Référence du type de données JSON — syntaxe complète pour les indications de type, SKIP, max_dynamic_paths et les fonctions d’introspection
- Choisir les types de données — recommandations générales pour choisir les types
- A New Powerful JSON Data Type for ClickHouse — analyse détaillée de l’architecture de stockage du type JSON
- Référence des formats JSON — formats d’entrée/sortie pour les données JSON (JSONEachRow, JSONAsObject, etc.)