Skip to main content

Description

Le format Protobuf est le format Protocol Buffers. Ce format nécessite un schéma de format externe, qui est mis en cache d’une requête à l’autre. ClickHouse prend en charge :
  • les syntaxes proto2 et proto3.
  • les champs Repeated/optional/required.
Pour établir la correspondance entre les colonnes de la table et les champs du type de message de Protocol Buffers, ClickHouse compare leurs noms. Cette comparaison est insensible à la casse, et les caractères _ (underscore) et . (point) sont considérés comme équivalents. Si les types d’une colonne et d’un champ du message Protocol Buffers sont différents, la conversion nécessaire est appliquée. Les messages imbriqués sont pris en charge. Par exemple, pour le champ z dans le type de message suivant :
ClickHouse essaie de trouver une colonne nommée x.y.z (ou x_y_z ou X.y_Z, etc.). Les messages imbriqués conviennent en entrée ou en sortie d’une structure de données imbriquée. Pour les champs mappés absents dans le format binaire :
  • Les colonnes mappées ordinaires non nullables utilisent la valeur par défaut du champ du schéma protobuf (proto2 [default = …], sinon la valeur par défaut du type) lors de l’analyse, et non l’expression DEFAULT de la table.
  • Les colonnes mappées Nullable(...) prennent la valeur NULL lorsque le champ est absent (elles n’utilisent pas la valeur par défaut du champ ou du type protobuf).
  • Lorsque input_format_protobuf_flatten_google_wrappers est activé pour les wrappers google.protobuf.*Value :
    • un wrapper absent sur une colonne Nullable(...) est traité comme un champ externe manquant et devient NULL ;
    • un wrapper présent mais vide (str {}) conserve la valeur par défaut du scalaire imbriqué ('' / 0) ;
    • une colonne non nullable mappée à un wrapper absent reçoit la valeur par défaut du scalaire imbriqué plutôt que NULL.
Les expressions DEFAULT de la table (et les expressions par défaut) s’appliquent aux colonnes de table qui n’ont aucun champ correspondant dans le type de message lorsque input_format_defaults_for_omitted_fields est activé (par défaut). Si ce paramètre est défini sur 0, les colonnes non mappées conservent la valeur par défaut du type de données insérée lors de l’analyse, au lieu de l’expression DEFAULT de la table. Exemple de valeur par défaut d’un champ de schéma proto2 (utilisée pour un champ mappé absent du message) :
Si un message contient oneof et que input_format_protobuf_oneof_presence est défini, ClickHouse remplit la colonne indiquant quel champ du oneof a été trouvé.
Le nom de la colonne qui indique la présence doit être identique au nom de oneof. Les messages imbriqués sont pris en charge (voir basic-examples). Les messages vides sont également pris en charge. Les types autorisés sont Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Enum, Enum8 ou Enum16. Enum (ainsi que Enum8 ou Enum16) doit contenir 0 pour indiquer l’absence ainsi que le tag de chaque cas de oneof ayant une colonne correspondante dans la table cible ; les représentations sous forme de chaîne n’ont pas d’importance. Pour les membres de message oneof sans colonne de table correspondante, les tags Enum manquants sont également autorisés. Si une telle branche est présente dans l’entrée, ClickHouse considère la présence du oneof comme omise et écrit 0 dans la colonne de présence. Le paramètre input_format_protobuf_oneof_presence est désactivé par défaut ClickHouse lit et écrit des messages protobuf au format length-delimited. Cela signifie qu’avant chaque message, sa longueur doit être encodée sous la forme d’un entier de longueur variable (varint).

Exemple d’utilisation

Lecture et écriture de données

Les fichiers utilisés dans cet exemple sont disponibles dans le repository examples
Dans cet exemple, nous allons lire des données à partir du fichier protobuf_message.bin dans une table ClickHouse. Nous les écrirons ensuite dans un fichier nommé protobuf_message_from_clickhouse.bin au format Protobuf. Étant donné le fichier schemafile.proto :
Si vous savez déjà comment sérialiser et désérialiser des données au format Protobuf, vous pouvez ignorer cette étape.Nous utiliserons Python pour sérialiser des données dans protobuf_message.bin et les lire dans ClickHouse. Si vous souhaitez utiliser un autre langage, voir aussi : “How to read/write length-delimited Protobuf messages in popular languages”.Exécutez la commande suivante pour générer un fichier Python nommé schemafile_pb2.py dans le même répertoire que schemafile.proto. Ce fichier contient les classes Python qui représentent votre message Protobuf UserData :
Créez maintenant un nouveau fichier Python nommé generate_protobuf_data.py, dans le même répertoire que schemafile_pb2.py. Collez-y le code suivant :
Exécutez maintenant le script en ligne de commande. Il est recommandé de l’exécuter depuis un environnement virtuel Python, par exemple avec uv :
Vous devrez installer la bibliothèque Python suivante :
Exécutez le script pour générer le fichier binaire :
Créez une table ClickHouse correspondant au schéma :
Insérez les données dans la table en ligne de commande :
Vous pouvez également écrire à nouveau les données dans un fichier binaire au format Protobuf :
Grâce à votre schéma Protobuf, vous pouvez désormais désérialiser les données que ClickHouse a écrites dans le fichier protobuf_message_from_clickhouse.bin.

Lecture et écriture de données avec ClickHouse Cloud

Avec ClickHouse Cloud, vous ne pouvez pas importer de fichier de schéma Protobuf. Vous pouvez toutefois utiliser le paramètre format_schema_source pour spécifier le schéma dans la requête. Dans cet exemple, nous vous montrons comment lire des données sérialisées depuis votre machine locale et les insérer dans une table dans ClickHouse Cloud. Comme dans l’exemple précédent, créez la table d’après le schéma Protobuf dans ClickHouse Cloud :
Le paramètre format_schema_source définit la source du paramètre format_schema Valeurs possibles :
  • ‘file’ (par défaut) : non pris en charge dans Cloud
  • ‘string’ : format_schema correspond au contenu littéral du schéma.
  • ‘query’ : format_schema est une requête permettant de récupérer le schéma.

format_schema_source='string'

Pour insérer les données dans ClickHouse Cloud en spécifiant le schéma sous forme de chaîne, exécutez :
Sélectionnez les données insérées dans la table :

format_schema_source='query'

Vous pouvez également stocker votre schéma Protobuf dans une table. Créez dans ClickHouse Cloud une table dans laquelle insérer des données :
Si vous avez exécuté l’exemple précédent, commencez par vider la table afin d’obtenir le même résultat que ci-dessous :
Insérez les données dans ClickHouse Cloud en spécifiant le schéma sous la forme d’une requête à exécuter. Envoyez cette insertion via l’interface HTTP : le serveur y analyse les données et exécute la requête de schéma, alors que clickhouse client analyse les données d’entrée côté client, où la requête de schéma échoue. L’option --url-query de curl (curl 7.87 et versions ultérieures) encode chaque paramètre au format URL ; la requête et la requête de schéma peuvent donc être écrites telles quelles :
Sélectionnez les données insérées dans la table :

Utilisation d’un schéma autogénéré

Si vous n’avez pas de schéma Protobuf externe pour vos données, vous pouvez tout de même écrire/lire des données au format Protobuf en utilisant un schéma autogénéré. Pour cela, utilisez le paramètre format_protobuf_use_autogenerated_schema. Par exemple :
Dans ce cas, ClickHouse générera automatiquement le schéma Protobuf à partir de la structure de la table à l’aide de la fonction structureToProtobufSchema. Il utilisera ensuite ce schéma pour sérialiser les données au format Protobuf. Vous pouvez également lire un fichier Protobuf avec le schéma autogénéré. Dans ce cas, il est nécessaire que le fichier soit créé à partir du même schéma :
Le paramètre format_protobuf_use_autogenerated_schema est activé par défaut et s’applique si format_schema n’est pas défini. Vous pouvez également enregistrer le schéma autogénéré dans le fichier lors des opérations d’entrée/sortie à l’aide du paramètre output_format_schema. Par exemple :
Dans ce cas, le schéma Protobuf autogénéré sera enregistré dans le fichier path/to/schema/schema.capnp.

Vider le cache Protobuf

Pour recharger le schéma Protobuf chargé à partir de format_schema_path, utilisez l’instruction SYSTEM DROP ... FORMAT CACHE.