Partie I : Faire de Schema-on-Read une réalité

Partie I : Faire de Schema-on-Read une réalité


(Remarque : ceci est le premier d’une série en deux parties expliquant comment nous traitons les données semi-structurées dans Snowflake)

Schéma? Je n’ai pas besoin de schéma puant !

Au cours des dernières années, j’ai entendu cette expression schema-on-read utilisée pour expliquer l’avantage de charger des données semi-structurées dans une plate-forme Big Data comme Hadoop. L’idée étant que vous pourriez retarder la modélisation des données et la conception des schémas longtemps après le chargement des données (afin de ne pas ralentir l’obtention de vos données en attendant ces maudits modélisateurs de données).

Chaque fois que je l’entendais, je pensais (et disais parfois) – « mais cela implique qu’il existe un schéma connaissable ». Donc, en réalité, vous ne faites que retarder le besoin inévitable de comprendre la structure afin de tirer une valeur commerciale de ces données. Payez-moi maintenant ou payez-moi plus tard.

Pourquoi retarder la douleur ?

Ainsi, même si les gens sont capables de charger rapidement ce type de données dans Hadoop ou NoSQL, il reste encore du travail à faire pour réellement séparer les données afin qu’elles puissent être analysées. La personne qui écrit la requête a souvent la charge de déterminer le schéma et d’écrire le code pour l’extraire. De plus, il peut y avoir une pénalité de performances de requête dans ce processus (par rapport à celle de l’interrogation des colonnes dans une base de données relationnelle).

Ce n’est pas le cas avec le Entrepôt de données élastique Snowflake (#ElasticDW)! Avec Snowflake, vous pouvez charger vos données semi-structurées directement dans une table relationnelle, puis interroger les données avec une instruction SQL, les joindre à d’autres données structurées, sans vous soucier des modifications futures du « schéma » de ces données. Snowflake garde en fait une trace du schéma auto-descriptif afin que vous n’ayez pas à le faire. Aucun ETL ou déchiquetage sophistiqué requis.

L’un des différenciateurs clés qui m’a vraiment attiré vers Snowflake est notre prise en charge intégrée charger et interroger données semi-structurées tels que JSON, XML et AVRO. Dans la plupart des entrepôts de données conventionnels et des environnements Big Data d’aujourd’hui, vous devez d’abord charger ce type de données sur une plate-forme Hadoop ou NoSQL, puis les broyer (en utilisant par exemple MapReduce) afin de les charger ensuite dans des colonnes dans une base de données relationnelle (qui est si vous souhaitez ensuite exécuter des requêtes SQL ou un outil BI/Analytics sur ces données).

Comment avons-nous fait ça?

Simple – nous avons inventé un nouveau type de données appelé UNE VARIANTE qui nous permet de charger des données semi-structurées (c’est-à-dire un schéma flexible) telles quelles dans une colonne d’un relationnel table.

Relisez cela – nous chargeons les données directement dans une table relationnelle.

D’accord, cela signifie donc qu’aucun Hadoop ou NoSQL n’est nécessaire dans votre architecture d’entrepôt de données uniquement pour contenir des données semi-structurées. Juste un SGBDR (dans le cloud) qui utilise SQL que votre personnel sait déjà écrire.

Mais ce n’est que la moitié de l’équation. Une fois les données entrées, comment les récupérer ?

Nos brillants fondateurs et notre excellente équipe d’ingénieurs (#DataSuperStars) ont créé des extensions de SQL pour référencer le schéma interne des données (il est auto-descriptif après tout) afin que vous puissiez interroger les composants et le joindre à des colonnes dans d’autres tables comme s’il avait été déchiqueté dans une table relationnelle standard. Sauf qu’il n’y a pas de codage ou de déchiquetage requis pour préparer les données. Cool.

Cela signifie également qu’à mesure que la source de données évolue et change au fil du temps (par exemple, de nouveaux attributs, une imbrication ou des tableaux sont ajoutés), aucun recodage du code ETL (ou même ELT) n’est nécessaire pour s’adapter. La UNE VARIANTE le type de données ne se soucie pas si le schéma varie.

A quoi ressemble-t-il vraiment ?

Assez de théorie – passons en revue un exemple de la façon dont tout cela fonctionne.

1 – Créer un tableau

J’ai déjà un compte Snowflake, une base de données et un entrepôt virtuel configurés, donc comme je le ferais dans n’importe quelle autre base de données, j’émets simplement un créer un tableau Instruction DDL :

create or replace table json_demo (v variant);

Maintenant, j’ai une table avec une colonne (« v ») avec un type de données déclaré de UNE VARIANTE.

2 – Charger des données

Maintenant, je charge un exemple de document JSON à l’aide d’un INSÉRER et notre PARSE_JSON fonction. Nous ne le chargeons pas simplement en tant que texte, mais le stockons plutôt en tant qu’objet dans le type de données VARIANT tout en le convertissant en un optimisé de colonne format (pour quand nous l’interrogerons plus tard):

insert into json_demo
 select
 parse_json(
 '{
     "fullName": "Johnny Appleseed",
     "age": 42,
     "gender": "Male",
     "phoneNumber": {
                     "areaCode": "415",
                     "subscriberNumber": "5551234"
                    },
     "children": [
                  { "name": "Jayden", "gender": "Male", "age": "10" },
                  { "name": "Emma", "gender": "Female", "age": "8" },
                  { "name": "Madelyn", "gender": "Female", "age": "6" }
                 ],
     "citiesLived": [
                    { "cityName": "London",
                      "yearsLived": [ "1989", "1993", "1998", "2002" ]
                    },
                    { "cityName": "San Francisco",
                      "yearsLived": [ "1990", "1993", "1998", "2008" ]
                    },
                    { "cityName": "Portland",
                      "yearsLived": [ "1993", "1998", "2003", "2005" ]
                    },
                    { "cityName": "Austin",
                      "yearsLived": [ "1973", "1998", "2001", "2005" ]
                    }
                   ]
  }');

3 – Commencez à extraire les données

Commençons donc par obtenir le nom :

select v:fullName from json_demo;

Obtenir le nom complet

Où:

v = le nom de la colonne dans la table json_demo

nom et prénom = attribut dans le schéma JSON

v:nomcomplet = notation pour indiquer quel attribut dans la colonne « v » nous voulons sélectionner.

Ainsi, à l’instar de la notation table.column avec laquelle tous les utilisateurs de SQL sont familiers, dans Snowflake, nous avons ajouté la possibilité de spécifier efficacement une colonne dans la colonne (c’est-à-dire une sous-colonne) qui est dérivée dynamiquement en fonction de la définition de schéma intégrée dans le Chaîne JSON.

4 – Casting des données

Habituellement, nous ne voulons pas voir les guillemets autour des données dans la sortie du rapport (sauf si nous allions créer un fichier d’extraction quelconque), nous pouvons donc le formater en tant que chaîne et lui donner un alias de colonne plus agréable (comme on ferait avec une colonne normale) :

select v:fullName::string as full_name
from json_demo;

Formater le nom complet

Examinons ensuite un peu plus les données en utilisant la même syntaxe ci-dessus :

select
   v:fullName::string as full_name,
   v:age::int as age,
   v:gender::string as gender
from json_demo;

Démographie

Encore une fois, SQL simple et la sortie ressemblent aux résultats de n’importe quelle table que vous pourriez avoir construite dans votre entrepôt de données traditionnel.

Sûr de dire à ce stade, avec ce que je vous ai déjà montré, vous pouvez regarder une table dans Snowflake avec une colonne VARIANT et commencer rapidement à « déchiqueter » le JSON avec SQL.

Combien de temps cela a-t-il pris pour apprendre ?

C’est pourquoi j’aime Snowflake ! Je peux maintenant interroger des données semi-structurées et j’ai fait ne pas dois apprendre un nouveau langage de programmation ou un nouveau cadre ou quoi que ce soit d’autre dans le pays du Big Data – pourtant j’ai les mêmes capacités que si j’avais.

Courbe d’apprentissage beaucoup plus faible à coup sûr.

Soyons un peu plus complexe

Oui, ces exemples sont très simples, alors approfondissons. Remarquez que dans la chaîne d’origine, il y a une certaine imbrication des données :

{
    "fullName": "Johnny Appleseed",
    "age": 42,
    "gender": "Male",
    "phoneNumber": {
                    "areaCode": "415",
                    "subscriberNumber": "5551234"
                   },
...

Comment pouvons-nous séparer cela? Avec une notation pointée table.column très familière :

select
   v:phoneNumber.areaCode::string as area_code,
   v:phoneNumber.subscriberNumber::string as subscriber_number
from json_demo;

Ainsi, tout comme fullName, age et gender sont des sous-colonnes, il en va de même pour phoneNumber. Et par la suite areaCode et subscriberNumber sont des sous-colonnes de la sous-colonne. Non seulement pouvons-nous séparer des objets imbriqués comme celui-ci, mais vous pouvez en déduire la facilité avec laquelle nous pouvons nous adapter si le schéma change et qu’une autre sous-colonne est ajoutée.

Que se passe-t-il si la structure change ?

Imaginez que lors d’un chargement ultérieur, le fournisseur ait modifié la spécification en ceci :

{
    "fullName": "Johnny Appleseed",
    "age": 42,
    "gender": "Male",
    "phoneNumber": {
                    "areaCode": "415",
                    "subscriberNumber": "5551234",
                    "extensionNumber": "24"
                   },
...

Ils ont ajouté un nouvel attribut (numéro de poste) ! Que devient la charge ?

Rien – cela continue de fonctionner parce que nous ingérons la chaîne dans le UNE VARIANTE colonne dans le tableau.

Qu’en est-il du code ETL ?

Quel code ETL ? Il y a pas d’ETL donc il n’y a rien à casser.

Qu’en est-il de existant rapports?

Ils continuent à travailler aussi. La requête précédente fonctionnera correctement. Si vous souhaitez voir la nouvelle colonne, le SQL doit être refactorisé pour tenir compte du changement :

select
   v:phoneNumber.areaCode::string as area_code,
   v:phoneNumber.subscriberNumber::string as subscriber_number,
   v:phoneNumber.extensionNumber::string as extension_number
from json_demo;

De plus, si l’inverse se produit et qu’un attribut est supprimé, la requête n’échouera pas. Au lieu de cela, il renvoie simplement une valeur NULL. De cette façon, nous isolons tout le code que vous écrivez de ce type de changements dynamiques.

La prochaine fois

Cet article a examiné les bases de la façon dont Snowflake gère les données semi-structurées, en utilisant JSON comme exemple spécifique. Dans Partie 2, Je vais vous montrer comment nous gérons des structures de schéma plus complexes comme les tableaux et les tableaux imbriqués dans le document JSON et vous donner un bref exemple d’agrégation et de filtrage par rapport au contenu d’un type de données VARIANT.

Liens supplémentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.