Cookies de statistiques et de publicité
Nous utilisons des cookies de statistiques et de publicité, tous deux destinés à Google. Si vous refusez, rien ne change visiblement pour vous.Aller à la page de confidentialité
Vous pouvez convertir NDJSON en Parquet gratuitement et sans compte : déposez le fichier ci-dessus et, une ou deux secondes plus tard, le résultat est prêt à télécharger. La conversion se fait dans votre propre navigateur : le fichier n’est donc jamais téléversé. Cela marche sous Windows, macOS et Linux comme sur iPhone et Android, et continue de marcher si vous coupez le réseau.
Jusqu’à 100 fichiers à la fois. Les formats mélangés ne posent pas de problème.
Ils sont convertis les uns après les autres et reviennent ensemble dans un ZIP.
NDJSON en Parquet
C’est ce qui rend la paire intéressante. Chaque ligne d’un fichier NDJSON est indépendante, ce qui est précisément la raison pour laquelle c’est le format auquel on ajoute : un nouveau champ peut être ajouté à l’écrivain un mardi et aucune ligne existante n’a besoin d’être réécrite. Sur quelques mois de déploiements, un seul fichier accumule plusieurs générations de formes d’enregistrement.
Parquet n’a aucune tolérance pour cela. Son pied de page déclare un ensemble fixé de colonnes avec un type chacune, et chaque ligne s’y conforme — ce qui permet à un moteur de requête de décrire un fichier de deux gigaoctets sans en lire une seule. Donc la conversion doit rapprocher les générations en un seul schéma, et tout ce qui suit est une conséquence de la manière dont elle le fait.
Un champ qui apparaît pour la première fois trois cent mille lignes plus loin dans le fichier devient quand même une colonne, et les lignes antérieures obtiennent des nulls. C’est la seule réconciliation qui ne peut pas perdre de données, et c’est la raison pour laquelle le lecteur fait une passe complète sur le fichier avant d’écrire quoi que ce soit.
La plupart des outils échantillonnent plutôt — les mille premières lignes, le premier mégaoctet — et c’est pourquoi un chargement qui a fonctionné sur un extrait de test échoue en production. L’échec est pire qu’une erreur : un schéma échantillonné écarte silencieusement chaque champ qu’il n’a pas vu. Tout lire coûte une passe sur les données et supprime entièrement cette catégorie de surprise, au prix décrit dans la section sur la mémoire ci-dessous.
L’autre moitié de la dérive est une clé qui a gardé son nom et changé de type. Un identifiant qui était un nombre et est maintenant entouré de guillemets, un statut qui était un booléen et est devenu une chaîne, une version qui est passée de 3 à « 3.1 » — tous apparaissent dans des fichiers d’événements de longue vie, généralement sans que personne ne le remarque sur le moment.
Le type de chaque colonne est décidé sur toutes ses valeurs : tout booléen donne BOOLEAN, tous les nombres entiers dans la plage 32 bits donnent INT32, les autres nombres donnent DOUBLE, et tout mélange donne une colonne en texte avec les valeurs numériques écrites en texte à côté. Une colonne en texte est visible, convertible en une seule expression, et ne supprime jamais silencieusement une ligne — ce que fait l’alternative, prendre le premier type et passer les autres à null. Si une colonne que vous attendiez numérique arrive en texte, interroger les valeurs qui échouent au cast est la façon la plus rapide de retrouver le jour où l’écrivain a changé.
Les événements structurés imbriquent par convention : un bloc `request`, un bloc `user`, un objet `context` portant un identifiant de trace. Parquet n’a nulle part où mettre un objet à l’intérieur d’une cellule, donc chaque enregistrement est d’abord aplati en ses feuilles et le chemin devient le nom de colonne — `request.method`, `user.id`, `context.trace_id`. Les types survivent à cela, parce qu’ils viennent du JSON plutôt que d’une re-analyse de texte.
Les tableaux sont le cas qui mérite un coup d’œil avant la conversion. Ils s’aplatissent par position, donc un tableau `tags` de a et b devient `tags.0` et `tags.1`, et l’ensemble des colonnes est l’union sur toutes les lignes du fichier — une liste vraiment longue quelque part dans un mois d’événements élargit le schéma pour tout le mois. Là où un champ est une liste à longueur vraiment variable, la joindre en une seule chaîne dans `jq` auparavant donne un schéma sur lequel on peut interroger plutôt qu’un schéma qu’il faut expliquer.
Parquet a un type entier 64 bits et cette conversion ne l’émet jamais. Les valeurs passent par les nombres JavaScript, qui portent 53 bits de précision entière, donc tout ce qui est hors de la plage 32 bits est écrit en DOUBLE plutôt que de prétendre à une exactitude qu’il n’a plus.
Les fichiers d’événements sont pleins de valeurs que cela touche : horodatages époque en millisecondes, identifiants à la snowflake, compteurs d’octets. Pour un horodatage, DOUBLE convient — la précision est bien au-delà de ce qu’une milliseconde demande. Pour un identifiant, non, et la correction se fait chez l’écrivain qui a produit les événements : émettre les identifiants comme chaînes JSON les garde exacts à travers toute cette pipeline et les fait arriver en colonne texte, ce qui est ce que devrait être un identifiant.
Cinquante mille enregistrements de commandes générés, comportant six champs, sont arrivés à 207 Ko en Parquet contre 4,8 Mo en NDJSON — plus de vingt pour un sur ces données. La forme de l’économie compte plus que le ratio, parce que le ratio dépend entièrement des données.
Deux choses se passent. Chaque ligne de NDJSON répète chaque clé, donc sur un enregistrement à six champs les noms de champ représentent une part substantielle des octets ; dans un stockage en colonnes chaque nom est écrit une fois, dans le pied de page. Et des valeurs d’une même catégorie assises côte à côte se compressent bien plus durement que les mêmes valeurs dispersées dans des lignes, ce qui explique qu’une colonne de ville ou de type d’événement ne coûte presque rien alors qu’une colonne de texte libre distinct sauve comparativement peu.
Il y a une vraie ironie ici. NDJSON existe pour qu’un consommateur n’ait jamais à tenir le fichier entier, et cette conversion tient le fichier entier — parce que la dernière ligne peut ajouter une colonne ou changer un type de colonne, et le pied de page ne peut pas être écrit tant que cela n’est pas connu.
Donc le plafond est la mémoire plutôt qu’un palier de plan. Le niveau gratuit accepte jusqu’à 100 Mo ; quelques dizaines de mégaoctets se convertissent sans drame et quelques centaines de mégaoctets sont le point où un onglet de navigateur peinerait. Au-delà, le format source est de votre côté : `split -l 500000` produit des fichiers valides, chacun se convertit de son côté, et un moteur de requête lit un répertoire de fichiers Parquet comme une seule table. C’est l’arrangement pour lequel ces moteurs sont faits, et c’est une meilleure réponse qu’un seul très gros fichier.
DuckDB lit le fichier dans une clause FROM, pandas en un seul appel, Spark comme une table native. La première chose à regarder est la liste des colonnes et ses types plutôt que les dix premières lignes, et il y a trois questions précises : quelles colonnes sont surtout null, lesquelles sont arrivées en texte alors qu’elles devraient être des nombres, et combien il y a de colonnes en tout.
Chaque réponse est un fait sur la source. Des colonnes surtout null marquent où la forme de l’enregistrement a changé ; des colonnes texte qui devraient être numériques marquent où un type a changé sous la même clé ; un nombre de colonnes plus grand que le nombre de champs marque un bloc imbriqué ou un tableau qui s’est aplati plus large que prévu. Vingt secondes passées sur le schéma économisent l’heure qu’il faut pour remarquer l’une de ces choses après que le fichier a été joint à autre chose.
L’unité naturelle pour cette conversion est une période plutôt qu’une histoire entière : un jour d’événements, un mois, un journal rotaté. Chacun se convertit en son propre fichier, et DuckDB, Spark et tout format de table de lac lisent un répertoire d’entre eux comme une seule table avec les schémas rapprochés à la lecture.
Cela gère aussi la dérive mieux qu’un seul fichier. Quand la forme de l’enregistrement change, les nouveaux fichiers portent les nouvelles colonnes et les anciens ne les portent pas, et le moteur de requête les rapproche à la lecture plutôt que le convertisseur à l’écriture. Partitionner par jour et convertir chaque jour une fois est la forme que ces données veulent, et cela signifie ne jamais reconvertir l’historique parce qu’un champ a été ajouté.
L’écrivain Parquet et l’analyse JSON sont tous deux du JavaScript ordinaire, chargés à la demande par cette page — pas de module WebAssembly, pas d’étape serveur. Aucune requête ne transporte le fichier ; il n’y a ni compte, ni file d’attente, ni palier de plan.
Pour la télémétrie c’est généralement le facteur décisif. Les flux d’événements contiennent des identifiants d’utilisateurs, des adresses IP, des chemins de requête et tout ce que l’application a éprouvé le besoin d’enregistrer, et le fait que ces données soient en route vers un entrepôt d’analyse ne fait pas d’un convertisseur web tiers un arrêt acceptable le long du parcours. Le registre marque aussi le support de Parquet comme inégal pour une raison : il est binaire et non éditable, donc si le fichier est destiné à une personne plutôt qu’à un moteur de requête, un tableur est la meilleure cible.
| NDJSON | Parquet | |
|---|---|---|
| Nom complet | Newline-Delimited JSON | Apache Parquet |
| Extension de fichier | .ndjson, .jsonl | .parquet |
| Type de média | application/x-ndjson | application/vnd.apache.parquet |
| Compression | — | Sans perte — rien n’est écarté |
| Première publication | 2013 | 2013 |
| Publié par | — | Apache Software Foundation |
| Licence | Standard ouvert | Standard ouvert |
| Situation actuelle | Actuel | Actuel |
| S’ouvre dans un navigateur | Aucun navigateur | Aucun navigateur |
| Envisagé à la place | JSON, CSV | CSV, JSON |
pandas lit aussi bien NDJSON que Parquet : vous pouvez comparer le résultat à l’original sans second logiciel.
Parquet vient de Apache Software Foundation et date de 2013. pandas, Apache Spark et DuckDB le lisent.
Non. Cette conversion se fait entièrement dans votre navigateur : le fichier ne quitte donc pas votre appareil. Vous pouvez le vérifier vous-même — ouvrez l’onglet réseau des outils de développement et convertissez quelque chose. Vous verrez la page elle-même et les requêtes de statistiques et de publicité qui financent ce service, et pas une seule qui transporte votre fichier. Le moteur de cette paire précise est parquet-wasm, une version WebAssembly du lecteur Apache Arrow ; votre navigateur le télécharge une fois puis le garde en cache.
Oui. Pas de compte, pas de filigrane et pas de quota journalier à dépenser : cela tourne sur votre propre machine, vous pouvez donc revenir autant de fois que vous voulez. Le navigateur traite des fichiers jusqu’à 100 Mo, 100 à la fois. parquet-wasm est téléchargé sur votre machine et s’y exécute, et c’est pourquoi rien n’est compté.
NDJSON et Parquet décrivent le contenu de façons radicalement différentes. La conversion est donc une reconstitution et non une copie : fidèle, mais pas identique octet pour octet. Les objets imbriqués sont aplatis en colonnes. Des données profondément imbriquées y perdent leur forme.
Pas pour la conversion : elle se fait dans le navigateur que vous avez déjà ouvert. Pour ouvrir le résultat, il vous faut ensuite le logiciel avec lequel votre appareil affiche habituellement Apache Parquet.