Quand utiliser le type JSON
JSON est conçu pour interroger, filtrer et agréger des champs spécifiques au sein d’objets JSON dont la structure est dynamique ou imprévisible. Il y parvient en décomposant les objets JSON en sous-colonnes distinctes, ce qui réduit considérablement le volume de données lu et accélère les requêtes sur les champs sélectionnés par rapport à des alternatives comme Map ou l’analyse de chaînes de caractères.
Cependant, cela implique des compromis importants :
INSERTplus lents - Décomposer le JSON en sous-colonnes, effectuer l’inférence de type et gérer des structures de stockage flexibles ralentit les insertions par rapport au stockage du JSON dans une simple colonneString.- Plus lent pour la lecture d’objets entiers - Si vous devez récupérer des documents JSON complets (plutôt que des champs spécifiques), le type
JSONest plus lent qu’une lecture depuis une colonneString. Le surcoût lié à la reconstruction des objets à partir de sous-colonnes distinctes n’apporte aucun bénéfice lorsque vous n’effectuez pas de requêtes au niveau des champs. - Surcoût de stockage - Le maintien de sous-colonnes distinctes ajoute un surcoût structurel par rapport au stockage du JSON sous la forme d’une unique valeur de chaîne.
Utilisez le type JSON lorsque :
- Vos données ont une structure dynamique ou imprévisible, avec des clés qui varient d’un document à l’autre
- Les types de champs ou les schémas évoluent au fil du temps, ou varient d’un enregistrement à l’autre
- Vous devez interroger, filtrer ou agréger des chemins spécifiques au sein d’objets JSON dont vous ne pouvez pas prévoir la structure à l’avance
- Votre cas d’utilisation porte sur des données semi-structurées, comme des logs, des événements ou du contenu généré par les utilisateurs, avec des schémas incohérents
Utilisez une colonne String (ou des types structurés) lorsque :
- La structure de vos données est connue et stable ; dans ce cas, utilisez plutôt des colonnes classiques ou les types
Tuple,Array,DynamicouVariant - Les documents
JSONsont traités comme des blobs opaques, uniquement stockés et récupérés dans leur intégralité, sans analyse au niveau des champs - Vous n’avez pas besoin d’interroger ni de filtrer des champs
JSONindividuels dans la base de données - Le
JSONsert simplement de format de transport/stockage et n’est pas analysé dans ClickHouse
Considérations et conseils pour l’utilisation de JSON
- Spécifiez les types des chemins à l’aide des indications dans la définition de colonne afin de définir les types des sous-colonnes connues et d’éviter une inférence de type inutile.
- Ignorez certains chemins si vous n’avez pas besoin des valeurs, avec SKIP and SKIP REGEXP afin de réduire le volume de stockage et d’améliorer les performances.
- Évitez de définir
max_dynamic_pathsà une valeur trop élevée : des valeurs importantes augmentent la consommation de ressources et réduisent l’efficacité. En règle générale, gardez-la en dessous de 10 000.
Indications de typeLes indications de type offrent bien plus qu’un simple moyen d’éviter une inférence de type inutile : elles éliminent entièrement l’indirection liée au stockage et au traitement. Les chemins JSON assortis d’indications de type sont toujours stockés comme des colonnes classiques, sans nécessiter de colonnes discriminantes ni de résolution dynamique à l’exécution de la requête. Cela signifie qu’avec des indications de type bien définies, les champs JSON imbriqués atteignent les mêmes performances et la même efficacité que s’ils avaient été modélisés dès le départ comme des champs de premier niveau. Par conséquent, pour les jeux de données globalement cohérents qui bénéficient malgré tout de la flexibilité de JSON, les indications de type constituent un moyen pratique de préserver les performances sans avoir à restructurer votre schéma ni votre pipeline d’ingestion.
Fonctionnalités avancées
- Les colonnes JSON peuvent être utilisées dans les clés primaires comme n’importe quelles autres colonnes. Il n’est pas possible de spécifier de codecs pour une sous-colonne.
- Elles prennent en charge l’introspection via des fonctions comme
JSONAllPathsWithTypes()andJSONDynamicPaths(). - Vous pouvez lire des sous-objets imbriqués à l’aide de la syntaxe
.^. - La syntaxe des requêtes peut différer du SQL standard et nécessiter des conversions de type ou des opérateurs spécifiques pour les champs imbriqués.
Exemples
tags soit ajoutée. S’il s’agissait simplement d’une liste de chaînes, nous pourrions la modéliser sous la forme d’un Array(String), mais supposons que vous puissiez ajouter des structures de tags arbitraires contenant des types mixtes (notez que score peut être une chaîne ou un entier). Voici notre document JSON modifié :
tags. Nous fournissons les deux exemples ci-dessous :
Nous fournissons une indication de type pour la colonne
update_date dans la définition JSON, car nous l’utilisons dans la clé de tri / clé primaire. Cela permet à ClickHouse de savoir que cette colonne ne sera pas NULL et de déterminer quelle sous-colonne update_date utiliser (il peut y en avoir plusieurs pour chaque type, ce qui serait ambigu sinon).JSONAllPathsWithTypes et du format de sortie PrettyJSONEachRow :
tags. Cette approche est généralement préférable, car elle réduit au minimum l’inférence requise de la part de ClickHouse :
tags.