Partager via


Modélisation des données dans Azure Cosmos DB for NoSQL

Bien que les bases de données sans schéma telles qu’Azure Cosmos DB facilitent le stockage et l’interrogation de données non structurées et semi-structurées, vous devez réfléchir à votre modèle de données afin d’optimiser les performances, la scalabilité et les coûts.

Comment les données sont stockées ? Comment votre application récupère-t-elle et interroge-t-elle des données ? Votre application exige-t-elle de nombreuses lectures (read heavy) ou de nombreuses écritures (write heavy) ?

Après avoir lu cet article, vous pourrez répondre aux questions suivantes :

  • Qu'est-ce que la modélisation de données et pourquoi dois-je m'en soucier ?
  • En quoi la modélisation des données dans Azure Cosmos DB est-elle différente de celle d’une base de données relationnelle ?
  • Comment exprimer les relations entre les données dans une base de données non relationnelle ?
  • Quand dois-je incorporer les données et quand dois-je créer un lien vers les données ?

Nombres dans JSON

Azure Cosmos DB enregistre des documents au format JSON. Il est donc important de déterminer s’il faut convertir des nombres en chaînes avant de les stocker dans JSON. Convertissez tous les nombres en String s’ils risquent de dépasser les limites des nombres en double précision telles que définies par l’Institute of Electrical and Electronics Engineers (IEEE) 754 binary64. La spécification JSON explique pourquoi l’utilisation de nombres en dehors de cette limite constitue une mauvaise pratique en raison de problèmes d’interopérabilité. Ces préoccupations sont particulièrement pertinentes pour la colonne de clé de partition, car elle est immuable et nécessite une migration de données s’il faut la modifier ultérieurement.

Incorporer des données

Lorsque vous modélisez des données dans Azure Cosmos DB, traitez vos entités en tant qu’éléments autonomes représentés sous la forme de documents JSON.

À des fins de comparaison, nous allons tout d’abord voir comment nous pouvons modéliser les données dans une base de données relationnelle. L'exemple suivant montre comment une personne peut être stockée dans une base de données relationnelle.

Capture d’écran d’un modèle de base de données relationnelle.

Quand vous utilisez des bases de données relationnelles, la stratégie consiste à normaliser toutes vos données. En général, la normalisation de vos données consiste à prendre une entité, une personne par exemple, et à la décomposer en composants discrets. Dans l’exemple, une personne peut avoir plusieurs enregistrements de coordonnées ainsi que plusieurs enregistrements d’adresse. Vous pouvez décomposer davantage les coordonnées en extrayant des champs communs tels que le type. La même approche s’applique aux adresses. Chaque enregistrement peut être classé comme Domicile ou Professionnel.

Le principe directeur lors de la normalisation des données consiste à éviter de stocker des données redondantes dans chaque enregistrement et à faire plutôt référence aux données. Dans cet exemple, pour lire une personne, avec ses coordonnées et ses adresses, vous devez utiliser des jointures pour recomposer (dénormaliser) efficacement vos données au moment de l’exécution.

SELECT p.FirstName, p.LastName, a.City, cd.Detail
FROM Person p
JOIN ContactDetail cd ON cd.PersonId = p.Id
JOIN ContactDetailType cdt ON cdt.Id = cd.TypeId
JOIN Address a ON a.PersonId = p.Id

La mise à jour des coordonnées et des adresses d’une seule personne nécessite des opérations d’écriture dans plusieurs tables individuelles.

Examinons à présent comment nous pourrions modéliser les mêmes données comme une entité autonome dans Azure Cosmos DB.

{
    "id": "1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "addresses": [
        {
            "line1": "100 Some Street",
            "line2": "Unit 1",
            "city": "Seattle",
            "state": "WA",
            "zip": 98012
        }
    ],
    "contactDetails": [
        {"email": "thomas@andersen.com"},
        {"phone": "+1 555 555-5555", "extension": 5555}
    ]
}

En utilisant cette approche, nous avons dénormalisé l’enregistrement de la personne, en incorporant toutes les informations la concernant (notamment ses coordonnées et adresses) dans un seul document JSON. En outre, étant donné que nous ne sommes pas limités à un schéma fixe, nous avons la possibilité d'avoir des coordonnées de formes entièrement différentes.

La récupération d’un enregistrement complet de personne dans la base de données correspond désormais à une seule opération de lecture portant sur un seul conteneur pour un seul élément. La mise à jour des coordonnées et adresses d’un enregistrement de personne correspond également à une seule opération d’écriture sur un élément unique.

La dénormalisation des données peut réduire le nombre de requêtes et de mises à jour dont nécessaires à votre application pour effectuer les opérations courantes.

Quand utiliser l'incorporation

En général, utilisez des modèles de données incorporés dans les cas suivants :

  • Il existe des relations de type contenu entre des entités.
  • Il existe des relations de type un-à-plusieurs entre des entités.
  • Les données changent peu fréquemment.
  • Les données ne croissent pas de manière illimitée.
  • Les données sont fréquemment interrogées ensemble.

Note

Normalement, les modèles de données dénormalisés offrent de meilleures performances en lecture .

Quand éviter l'incorporation

Bien que la règle générale dans Azure Cosmos DB consiste à tout dénormaliser et à incorporer toutes les données dans un seul élément, cette approche peut mener à des situations qu’il vaut mieux éviter.

Prenons cet extrait de code JSON.

{
    "id": "1",
    "name": "What's new in the coolest Cloud",
    "summary": "A blog post by someone real famous",
    "comments": [
        {"id": 1, "author": "anon", "comment": "something useful, I'm sure"},
        {"id": 2, "author": "bob", "comment": "wisdom from the interwebs"},
        …
        {"id": 100001, "author": "jane", "comment": "and on we go ..."},
        …
        {"id": 1000000001, "author": "angry", "comment": "blah angry blah angry"},
        …
        {"id": ∞ + 1, "author": "bored", "comment": "oh man, will this ever end?"},
    ]
}

Une entité post avec commentaires incorporés pourrait avoir cet aspect si nous modélisions un blog ou un système de gestion de contenu (CMS) classique. Dans cet exemple, le problème est que le tableau de commentaires est illimité, c’est-à-dire qu’il n’existe aucune limite (pratique) au nombre de commentaires possibles pour une publication. Cette conception peut poser problème, car la taille de l’élément risque de croître indéfiniment ; il convient donc de l’éviter.

À mesure que la taille de l’élément augmente, la transmission, la lecture et la mise à jour des données à grande échelle deviennent plus complexes.

Dans ce cas, il serait préférable de considérer le modèle de données suivant.

Post item:
{
    "id": "1",
    "name": "What's new in the coolest Cloud",
    "summary": "A blog post by someone real famous",
    "recentComments": [
        {"id": 1, "author": "anon", "comment": "something useful, I'm sure"},
        {"id": 2, "author": "bob", "comment": "wisdom from the interwebs"},
        {"id": 3, "author": "jane", "comment": "....."}
    ]
}

Comment items:
[
    {"id": 4, "postId": "1", "author": "anon", "comment": "more goodness"},
    {"id": 5, "postId": "1", "author": "bob", "comment": "tails from the field"},
    ...
    {"id": 99, "postId": "1", "author": "angry", "comment": "blah angry blah angry"},
    {"id": 100, "postId": "2", "author": "anon", "comment": "yet more"},
    ...
    {"id": 199, "postId": "2", "author": "bored", "comment": "will this ever end?"}   
]

Ce modèle comporte un document pour chaque commentaire, avec une propriété qui contient l’identificateur de publication. Ce modèle permet aux publications de contenir un nombre illimité de commentaires et de se développer efficacement. Les utilisateurs qui souhaitent afficher plus de commentaires que les commentaires les plus récents interrogent ce conteneur en transmettant l’ID de publication qui doit être la clé de partition pour le conteneur de commentaires.

Il existe un autre cas de figure où l’incorporation de données est déconseillée : quand les données incorporées sont souvent utilisées dans les différents éléments et changent fréquemment.

Prenons cet extrait de code JSON.

{
    "id": "1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "holdings": [
        {
            "numberHeld": 100,
            "stock": { "symbol": "zbzb", "open": 1, "high": 2, "low": 0.5 }
        },
        {
            "numberHeld": 50,
            "stock": { "symbol": "xcxc", "open": 89, "high": 93.24, "low": 88.87 }
        }
    ]
}

Cet exemple pourrait représenter le portefeuille d’actions d’une personne. Nous avons choisi d’incorporer les informations boursières dans chaque document de portefeuille. Dans un environnement où les données liées changent fréquemment, l’incorporation de ces données va vous obliger à mettre à jour constamment chaque portefeuille. En prenant l’exemple d’une application de trading d’actions, vous mettriez à jour chaque élément de portefeuille chaque fois qu’une action est échangée.

L’action zbzb peut être échangée des centaines de fois en une seule journée, et des milliers d’utilisateurs pourraient détenir zbzb dans leurs portefeuilles. Avec un modèle de données tel que celui de l’exemple, le système doit mettre à jour des milliers de documents de portefeuille plusieurs fois par jour, ce qui n’est pas viable à grande échelle.

Données de référence

L’incorporation de données fonctionne bien dans la plupart des cas, mais il existe des scénarios où la dénormalisation des données cause plus de problèmes qu’elle n’en résout. Alors, que faire ?

Vous pouvez créer des relations entre des entités dans des bases de données orientées documents, et non uniquement dans les bases de données relationnelles. Dans une base de données orientée documents, un élément peut inclure des informations qui se connectent aux données d’autres documents. Azure Cosmos DB n’est pas conçu pour des relations complexes comme celles des bases de données relationnelles, mais des liens simples entre les éléments sont possibles et peuvent s’avérer utiles.

Dans le code JSON, nous avons choisi d’utiliser l’exemple de portefeuille d’actions précédent, mais cette fois-ci, nous faisons référence à l’action dans le portefeuille au lieu de l’incorporer. Ainsi, lorsque l’action change fréquemment au cours de la journée, le seul élément à mettre à jour est le document d’action (stock).

Person document:
{
    "id": "1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "holdings": [
        { "numberHeld":  100, "stockId": 1},
        { "numberHeld":  50, "stockId": 2}
    ]
}

Stock documents:
{
    "id": "1",
    "symbol": "zbzb",
    "open": 1,
    "high": 2,
    "low": 0.5,
    "vol": 11970000,
    "mkt-cap": 42000000,
    "pe": 5.89
},
{
    "id": "2",
    "symbol": "xcxc",
    "open": 89,
    "high": 93.24,
    "low": 88.87,
    "vol": 2970200,
    "mkt-cap": 1005000,
    "pe": 75.82
}

L’un des inconvénients de cette approche est que votre application doit effectuer plusieurs requêtes à la base de données pour obtenir des informations relatives à chaque action du portefeuille d’une personne. Cette conception accélère l’écriture de données, car les mises à jour sont fréquentes. Toutefois, cela ralentit la lecture ou l’interrogation des données, ce qui est moins important pour ce système.

Note

Les modèles de données normalisés peuvent nécessiter davantage d’aller-retour jusqu’au serveur.

Qu'en est-il des clés étrangères ?

Étant donné qu’il n’existe aucun concept de contrainte, comme une clé étrangère, la base de données ne vérifie aucune relation entre documents ; ces liens sont donc « faibles ». Si vous souhaitez vous assurer que les données auxquelles un élément fait référence existent, vous devez effectuer cette étape dans votre application, ou en utilisant des déclencheurs côté serveur ou des procédures stockées sur Azure Cosmos DB.

Quand utiliser des références

En général, utilisez des modèles de données normalisés dans les cas suivants :

  • Représentation des relations un-à-plusieurs .
  • Représentation des relations plusieurs-à-plusieurs .
  • Les données associées changent fréquemment.
  • Les données référencées peuvent être illimitées.

Note

En général, la normalisation offre de meilleures performances en écriture .

Où placer la relation ?

La croissance de la relation permet de déterminer dans quel élément doit être stockée la référence.

Si nous observons le code JSON qui modélise les éditeurs et les livres :

Publisher document:
{
    "id": "mspress",
    "name": "Microsoft Press",
    "books": [ 1, 2, 3, ..., 100, ..., 1000]
}

Book documents:
{"id": "1", "name": "Azure Cosmos DB 101" }
{"id": "2", "name": "Azure Cosmos DB for RDBMS Users" }
{"id": "3", "name": "Taking over the world one JSON doc at a time" }
...
{"id": "100", "name": "Learn about Azure Cosmos DB" }
...
{"id": "1000", "name": "Deep Dive into Azure Cosmos DB" }

Si le nombre de livres par éditeur est restreint et que la croissance est limitée, il peut être utile de stocker la référence du livre dans le document d’éditeur (publisher). Toutefois, si le nombre de livres par éditeur est illimité, ce modèle de données aboutira à des tableaux mutables, croissants, comme dans l’exemple de document d’éditeur.

Modifier la structure permet d’obtenir un modèle qui représente les mêmes données tout en évitant les collections volumineuses et mutables.

Publisher document:
{
    "id": "mspress",
    "name": "Microsoft Press"
}

Book documents:
{"id": "1","name": "Azure Cosmos DB 101", "pub-id": "mspress"}
{"id": "2","name": "Azure Cosmos DB for RDBMS Users", "pub-id": "mspress"}
{"id": "3","name": "Taking over the world one JSON doc at a time", "pub-id": "mspress"}
...
{"id": "100","name": "Learn about Azure Cosmos DB", "pub-id": "mspress"}
...
{"id": "1000","name": "Deep Dive into Azure Cosmos DB", "pub-id": "mspress"}

Dans cet exemple, le document d’éditeur ne contient plus de collection indépendante. À la place, chaque document de livre inclut une référence à son éditeur.

Comment modéliser des relations plusieurs-à-plusieurs ?

Dans une base de données relationnelle, les relations plusieurs-à-plusieurs sont souvent modélisées à l’aide de tables de jointure. Ces relations se contentent de joindre des enregistrements d’autres tables ensemble.

Capture d’écran montrant comment joindre des tables.

Vous pouvez être tenté de répliquer la même chose à l'aide de documents et de générer un modèle de données qui ressemble à ce qui suit.

Author documents:
{"id": "a1", "name": "Thomas Andersen" }
{"id": "a2", "name": "William Wakefield" }

Book documents:
{"id": "b1", "name": "Azure Cosmos DB 101" }
{"id": "b2", "name": "Azure Cosmos DB for RDBMS Users" }
{"id": "b3", "name": "Taking over the world one JSON doc at a time" }
{"id": "b4", "name": "Learn about Azure Cosmos DB" }
{"id": "b5", "name": "Deep Dive into Azure Cosmos DB" }

Joining documents:
{"authorId": "a1", "bookId": "b1" }
{"authorId": "a2", "bookId": "b1" }
{"authorId": "a1", "bookId": "b2" }
{"authorId": "a1", "bookId": "b3" }

Cette approche fonctionne, mais le chargement d’un auteur avec ses livres ou d’un livre avec son auteur nécessite toujours au moins deux requêtes supplémentaires à la base de données. Une requête pour l’élément de jointure (joining) et une autre requête pour extraire l’élément joint.

Si cette jointure ne fait rien d’autre que coller ensemble deux données, pourquoi ne pas la supprimer complètement ? Considérez l'exemple suivant.

Author documents:
{"id": "a1", "name": "Thomas Andersen", "books": ["b1", "b2", "b3"]}
{"id": "a2", "name": "William Wakefield", "books": ["b1", "b4"]}

Book documents:
{"id": "b1", "name": "Azure Cosmos DB 101", "authors": ["a1", "a2"]}
{"id": "b2", "name": "Azure Cosmos DB for RDBMS Users", "authors": ["a1"]}
{"id": "b3", "name": "Learn about Azure Cosmos DB", "authors": ["a1"]}
{"id": "b4", "name": "Deep Dive into Azure Cosmos DB", "authors": ["a2"]}

Avec ce modèle, vous pouvez facilement voir quels livres un auteur a écrits en consultant son document. Vous pouvez également voir quels auteurs ont écrit un livre en vérifiant le document de livre. Vous n’avez pas besoin d’utiliser une table de jointure distincte ou d’effectuer des requêtes supplémentaires. Ce modèle simplifie et accélère l’obtention des données dont votre application a besoin.

Modèles de données hybrides

Nous explorons l’incorporation (ou la dénormalisation) et le référencement (ou normalisation) des données. Chaque approche offre des avantages et implique des compromis.

Il n’est pas toujours nécessaire de choisir l’une ou l’autre. N’hésitez pas à mélanger un peu les approches.

En fonction des modèles d’utilisation et des charges de travail spécifiques de votre application, mélanger des données incorporées et référencées peut s’avérer judicieux. Cette approche peut simplifier la logique de l’application, réduire les allers-retours avec le serveur et maintenir de bonnes performances.

Examinons le code JSON suivant.

Author documents:
{
    "id": "a1",
    "firstName": "Thomas",
    "lastName": "Andersen",
    "countOfBooks": 3,
    "books": ["b1", "b2", "b3"],
    "images": [
        {"thumbnail": "https://....png"}
        {"profile": "https://....png"}
        {"large": "https://....png"}
    ]
},
{
    "id": "a2",
    "firstName": "William",
    "lastName": "Wakefield",
    "countOfBooks": 1,
    "books": ["b1"],
    "images": [
        {"thumbnail": "https://....png"}
    ]
}

Book documents:
{
    "id": "b1",
    "name": "Azure Cosmos DB 101",
    "authors": [
        {"id": "a1", "name": "Thomas Andersen", "thumbnailUrl": "https://....png"},
        {"id": "a2", "name": "William Wakefield", "thumbnailUrl": "https://....png"}
    ]
},
{
    "id": "b2",
    "name": "Azure Cosmos DB for RDBMS Users",
    "authors": [
        {"id": "a1", "name": "Thomas Andersen", "thumbnailUrl": "https://....png"},
    ]
}

Ici nous avons suivi (principalement) le modèle incorporé, où les données des autres entités sont incorporées dans le document de niveau supérieur, mais les autres données sont référencées.

Dans le document de livre (book), nous pouvons voir quelques champs intéressants lorsque nous examinons le tableau des auteurs. Il existe un champ id que nous utilisons pour faire référence à un document d’auteur (author), une pratique courante dans un modèle normalisé, mais nous disposons également des champs name et thumbnailUrl. Nous pourrions utiliser uniquement id et laisser l’application récupérer toutes les informations supplémentaires dont elle a besoin à partir de l’élément auteur correspondant via le « lien ». Toutefois, étant donné que l’application affiche le nom de l’auteur et une image miniature pour chaque livre, la dénormalisation de certaines données de l’auteur permet de réduire le nombre d’allers-retours avec le serveur pour chaque livre d’une liste.

Si le nom de l’auteur change ou s’il met à jour sa photo, vous devrez mettre à jour chaque livre qu’il a publié. Toutefois, pour cette application, en supposant que les auteurs changent rarement de nom, ce compromis constitue une décision de conception acceptable.

Dans cet exemple, il existe des valeurs d’agrégat précalculé pour économiser un traitement coûteux pendant une opération de lecture. Dans l’exemple, certaines données incorporées dans l’élément d’auteur (author) sont des données calculées au moment de l’exécution. À chaque publication d’un nouveau livre, un élément de type livre est créé et le champ countOfBooks est défini sur une valeur calculée en fonction du nombre de documents de type livre existant pour un auteur particulier. Cette optimisation serait appropriée dans les systèmes qui exigent de nombreuses lectures (read heavy), où nous pouvons nous permettre d'effectuer des calculs sur les écritures afin d'optimiser les lectures.

L’existence d’un modèle avec des champs précalculés est possible, car Azure Cosmos DB prend en charge les transactions multidocuments. De nombreux magasins NoSQL, qui ne peuvent pas effectuer des transactions sur plusieurs documents, recommandent des décisions de conception telles que « tout incorporer systématiquement » en raison de cette limitation. Avec Azure Cosmos DB, vous pouvez utiliser des déclencheurs côté serveur, ou des procédures stockées, qui insèrent des livres et mettent à jour les auteurs au sein d’une transaction ACID. Aujourd’hui, vous n’êtes pas tenu d’intégrer tous les éléments dans un seul élément, simplement pour vous assurer que vos données restent cohérentes.

Faire la distinction entre les différents types d’éléments

Dans certains scénarios, vous souhaiterez combiner différents types d’éléments dans la même collection ; ce choix de conception est généralement retenu quand vous souhaitez que plusieurs documents connexes se trouvent dans la même partition. Par exemple, vous pourriez placer les livres et les critiques de livre dans la même collection et la partitionner par bookId. Dans une telle situation, vous souhaitez généralement ajouter à vos documents un champ qui identifie leur type afin de les différencier.

Book documents:
{
    "id": "b1",
    "name": "Azure Cosmos DB 101",
    "bookId": "b1",
    "type": "book"
}

Review documents:
{
    "id": "r1",
    "content": "This book is awesome",
    "bookId": "b1",
    "type": "review"
}
{
    "id": "r2",
    "content": "Best book ever!",
    "bookId": "b1",
    "type": "review"
}

Modélisation des données pour la mise en miroir de Microsoft Fabric et d'Azure Cosmos DB

La mise en miroir Azure Cosmos DB est une fonctionnalité de traitement transactionnel et analytique hybride (HTAP) native cloud qui vous permet d’exécuter des analyses en quasi temps réel sur des données opérationnelles dans Azure Cosmos DB. La mise en miroir de structure crée une intégration transparente entre Azure Cosmos DB et OneLake dans Microsoft Fabric.

Cette intégration vous permet d’exécuter des requêtes rapides et abordables sur de grands ensembles de données. Vous n’avez pas besoin de copier les données ou de vous soucier de l’impact de votre charge de travail transactionnelle. Lorsque vous activez la mise en miroir d’un conteneur, chaque modification apportée à vos données est copiée dans OneLake presque immédiatement. Vous n’avez pas besoin de configurer le flux de modification ni d’exécuter des tâches d’extraction, de transformation et de chargement (ETL). Le système maintient automatiquement les deux magasins de données synchronisés pour vous.

Avec la mise en miroir Azure Cosmos DB, vous pouvez désormais vous connecter directement à vos conteneurs Azure Cosmos DB à partir de Microsoft Fabric et accéder à vos données sans coût en unités de requête (request units), en utilisant des requêtes T-SQL via le point de terminaison SQL vers vos données ou directement via Spark depuis OneLake.

Inférence de schéma automatique

Le magasin transactionnel Azure Cosmos DB consiste en des données semi-structurées orienté ligne, tandis que OneLake dans Microsoft Fabric utilise un format structuré en colonnes. Cette conversion est automatiquement effectuée pour les clients. Le processus de conversion est limité : nombre maximal de niveaux imbriqués, nombre maximal de propriétés, types de données non pris en charge, etc.

Note

Dans le contexte du magasin analytique, nous considérons les structures suivantes comme des propriétés :

  • « Éléments » ou « paires chaîne-valeur séparées par le signe : » JSON
  • Objets JSON, délimités par les signes { et }
  • Tableaux JSON, délimités par les signes [ et ]

Vous pouvez réduire l’effet des conversions d’inférences du schéma et optimiser vos capacités analytiques à l’aide des techniques suivantes.

Normalization

La normalisation devient moins pertinente, car Microsoft Fabric vous permet de joindre des conteneurs à l’aide de T-SQL ou Spark SQL. Les avantages attendus de la normalisation sont les suivants :

  • Empreinte de données réduite
  • Réduction de la taille des transactions
  • Réduction du nombre de propriétés par document
  • Réduction du nombre de niveaux imbriqués dans les structures de données

Avoir moins de propriétés et moins de niveaux dans vos données accélère les requêtes analytiques. Il permet également de s’assurer que toutes les parties de vos données sont incluses dans OneLake. Il existe des limites au nombre de niveaux et de propriétés représentés dans OneLake.

Un autre facteur important pour la normalisation est que OneLake prend en charge les jeux de résultats avec jusqu’à 1 000 colonnes, et qu'exposer des colonnes imbriquées compte également dans cette limite. En d’autres termes, les points de terminaison SQL dans Fabric ont une limite de 1 000 propriétés.

Mais que faire étant donné que la dénormalisation constitue une technique importante de modélisation des données pour Azure Cosmos DB ? Vous devez trouver le bon équilibre pour vos charges de travail transactionnelles et analytiques.

Clé de partition

La clé de partition Azure Cosmos DB (PK) n’est pas utilisée dans Microsoft Fabric. En raison de cette isolation, vous pouvez choisir un PK pour vos données transactionnelles en mettant l'accent sur l'ingestion des données et les lectures ponctuelles, tandis que les requêtes entre partitions peuvent être effectuées à l'aide de Microsoft Fabric. Prenons un exemple :

Dans un scénario IoT global hypothétique, device id sert de clé de partition appropriée, car tous les appareils génèrent un volume similaire de données, ce qui empêche les problèmes de partition chaude. En revanche, si vous souhaitez analyser les données de plusieurs appareils (par exemple « toutes les données d’hier » ou « totaux par ville »), vous risquez de rencontrer des problèmes dans la mesure où il s’agit de requêtes entre partitions. Ces requêtes peuvent nuire à vos performances transactionnelles, car elles utilisent pour s’exécuter une partie de votre débit d’unités de requête. Toutefois, avec Microsoft Fabric, vous pouvez exécuter ces requêtes analytiques sans coût d’unités de requête. Le format delta dans OneLake est optimisé pour les requêtes analytiques.

Types de données et nom des propriétés

L’article sur les règles d’inférence automatique du schéma présente les types de données pris en charge. Bien que les runtimes Microsoft Fabric puissent traiter les types de données pris en charge différemment, les types de données non pris en charge bloquent la représentation dans le magasin analytique. Voici un exemple : lorsque vous utilisez des chaînes DateTime qui suivent la norme UTC ISO 8601, les pools Spark dans Microsoft Fabric représentent ces colonnes comme string et SQL serverless représentent ces colonnes comme varchar(8000).

Aplatissement de données

Chaque propriété située au niveau supérieur de vos données Azure Cosmos DB devient une colonne dans le magasin analytique. Les propriétés à l’intérieur d’objets ou de tableaux imbriqués sont stockées en tant que JSON dans OneLake. Les structures imbriquées demandent un traitement supplémentaire dans les runtimes Spark ou SQL pour aplatir les données. Cela peut ajouter des coûts de calcul et une latence lors de la gestion de très grandes quantités de données. Là où il est simple de le faire, utilisez un modèle de données plat pour vos données. Au minimum, évitez l’imbrication excessive des données dans vos modèles de données.

L’élément n’a que deux colonnes dans OneLake, id et contactDetails. Toutes les autres données, y compris email et phone, nécessitent un traitement supplémentaire via des fonctions SQL ou Spark pour être lues.

{
    "id": "1",
    "contactDetails": [
        {"email": "thomas@andersen.com"},
        {"phone": "+1 555 555-5555"}
    ]
}

L’aplatissement élimine ce besoin. Ici ci-dessous, id, emailet phone sont tous directement accessibles en tant que colonnes sans traitement supplémentaire

{
    "id": "1",
    "email": "thomas@andersen.com",
    "phone": "+1 555 555-5555"
}

Hiérarchisation des données

Microsoft Fabric vous permet de réduire les coûts des perspectives suivantes :

  • Moins de requêtes s’exécutent dans votre base de données transactionnelle.
  • Il utilise une clé de partition optimisée pour l’ingestion des données et les lectures ponctuelles (ce qui réduit l’empreinte des données), les scénarios de partitionnement à chaud et les fractionnements de partitions.
  • Aucun travail ETL ne s’exécute dans votre environnement, ce qui vous évite d’avoir à leur allouer des unités de requête.

Redondance contrôlée

Cette technique constitue une excellente solution de remplacement pour les situations dans lesquelles il existe déjà un modèle de données qui ne peut pas être modifié. Ou si vos données sont trop complexes avec trop de niveaux imbriqués ou trop de propriétés. Si ce scénario est votre cas, vous pouvez utiliser le flux de modification Azure Cosmos DB pour répliquer vos données dans un autre conteneur, en appliquant les transformations requises, puis configurer la mise en miroir pour ce conteneur à Microsoft Fabric pour l’analytique. Prenons un exemple :

Scénario

Le conteneur CustomersOrdersAndItems est utilisé pour stocker des commandes en ligne, notamment les détails du client et des éléments : adresse de facturation, adresse de livraison, méthode de livraison, état de livraison, prix des articles, etc. Seules les 1 000 premières propriétés sont représentées et les informations clés ne sont pas incluses, ce qui rend l’analytique impossible dans Fabric. Le conteneur a des pétaoctets de données afin qu’il ne soit pas possible de modifier l’application et de remodeler les données.

Le volume important de données constitue un autre aspect du problème. Des milliards de lignes sont constamment utilisées par le service d’analytique, ce qui l’empêche de se servir de la durée de vie transactionnelle pour la suppression d’anciennes données. La maintenance de l’historique des données dans la base de données transactionnelle en raison des besoins analytiques les force à augmenter constamment les RU/s, ce qui a un impact sur les coûts. Les charges de travail transactionnelles et analytiques entrent en concurrence pour les mêmes ressources à un instant t.

que pouvez-vous faire ?

Solution avec le flux de modification

  • La solution utilise le flux de modification pour remplir trois nouveaux conteneurs : Customers, Orderset Items. Avec le flux de modification, vous pouvez normaliser et aplatir les données et supprimer les informations inutiles du modèle de données.
  • Le conteneur CustomersOrdersAndItems possède maintenant une durée de vie (TTL) permettant de conserver les données pendant six mois seulement, ce qui réduit encore l’utilisation des unités de requête. Il existe en effet un minimum de 10 unités de requête par Go dans Azure Cosmos DB. Moins de données, moins d’unités de requête.

Takeaways

Le point essentiel à retenir de cet article est que la modélisation des données dans un scénario sans schéma est aussi importante que jamais.

De même qu’il n’existe pas de manière unique de représenter une donnée à l’écran, vous pouvez modéliser vos données de différentes façons. Vous devez comprendre votre application et comment elle produit, utilise et traite les données. En appliquant certaines des instructions présentées ici, vous pouvez créer un modèle qui répond aux besoins immédiats de votre application. Lorsque votre application évolue, profitez de la flexibilité d’une base de données sans schéma pour adapter et faire progresser facilement votre modèle de données.