Recherche…


Introduction

La base de données Firebase est une base de données NoSQL qui stocke ses données sous la forme d'objets JSON hiérarchiques. Il n'y a pas de tables ou d'enregistrements de forme quelconque, comme une base de données SQL aurait normalement, juste des noeuds qui constituent une structure clé-valeur.

Normalisation des données

Pour avoir une structure de base de données correctement conçue, les exigences en matière de données doivent être soigneusement définies et anticipées. La structure dans ce cas devrait être normalisée; plus l'arborescence JSON est plate, plus l'accès aux données est rapide.

À faire et à ne pas faire

La mauvaise direction

Considérons la structure suivante

{
  "users": {

    // Uniquely generated IDs for children is common practice,
    // it's actually really useful for automating child creation.
    // Auto-incrementing an integer for a key can be problematic when a child is removed.

    "-KH3Cx0KFvSQELIYZezv": {     
      "name": "Jon Snow",
      "aboutMe": "I know nothing...",
      "posts": {
        "post1": { 
          "body": "Different roads sometimes leads to the same castle", 
          "isHidden": false
        },
        "post2": { ... },
        // Possibly more posts
      }
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },     // Another user
    // A lot more users here
  }
}

C'est un excellent exemple de ce qu'il ne faut pas faire. Les structures multi-imbriquées, telles que celle ci-dessus, peuvent être très problématiques et entraîner un revers de performance considérable.

La manière dont Firebase accède à un nœud consiste à télécharger toutes les données des enfants, puis à les parcourir sur tous les nœuds de même niveau (tous les enfants des parents). Maintenant, imaginez une base de données avec plusieurs utilisateurs , chacun ayant des centaines (voire des milliers) de messages . L'accès à une publication dans ce cas pourrait potentiellement charger des centaines de mégaoctets de données inutilisées. Dans une application plus complexe, l'imbrication pourrait être plus profonde que 4 couches, ce qui entraînerait davantage de téléchargements et d'itérations inutiles.

Le droit chemin

Aplatir la même structure ressemblerait à ceci

{
  // "users" should not contain any of the posts' data
  "users": {
    "-KH3Cx0KFvSQELIYZezv": {
      "name": "Jon Snow",
      "aboutMe": "I know nothing..."
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },
    // More users
  },

  // Posts can be accessed provided a user key
  "posts": {
    "-KH3Cx0KFvSQELIYZezv": {     // Jon Snow's posts
      "post1": { 
        "body": "Different roads sometimes leads to the same castle", 
        "isHidden": false
      },
      "post2": { ... },
      // Possibly more posts
    },
    "-KH3Dx2KFdSLErIYZcgk": { ... },
    // other users' posts
  }
}

Cela évite une énorme surcharge en itérant sur moins de nœuds pour accéder à un objet cible. Tous les utilisateurs qui n’ont pas de messages n’existeraient pas dans la branche des publications et, par conséquent, l’itération sur ces utilisateurs dans le mauvais sens ci-dessus est totalement inutile.

Relations bidirectionnelles

Voici un exemple de base de données collégiale simple et minimale qui utilise des relations bidirectionnelles

{
  "students": {
    "-SL3Cs0KFvDMQLIYZEzv": {
      "name": "Godric Gryffindor",
      "id": "900130309",
      "courses": {
         "potions": true,
         "charms": true,
         "transfiguration": true, 
      }
    },
    "-SL3ws2KvZQLTYMqzSas": {          
      "name": "Salazar Slytherin",
      "id": "900132319",
      "courses": {
         "potions": true,
         "herbs": true,
         "muggleStudies": true, 
      }
    },
    "-SL3ns2OtARSTUMywqWt": { ... },
    // More students here
  },

  "courses": {
    "potions": {
      "code": "CHEM305",
      "enrolledStudents": {
        "-SL3Cs0KFvDMQLIYZEzv": true,     // Godric Gryffindor
        "-SL3ws2KvZQLTYMqzSas": true,     // Salazar Slytherin
        // More students
      }
    },
    "muggleStuddies": {
      "code": "SOC215",
      "enrolledStudents": {
        "-SL3ws2KvZQLTYMqzSas": true,     // Salazar Slytherin
        "-SL3ns2OtARSTUMywqWt": true,     // Some other student
        // More students
      }
    },
    // More courses
  }
}

Notez que chaque élève a une liste de cours et chaque cours a une liste d' étudiants inscrits.

La redondance n'est pas toujours une mauvaise approche. Il est vrai que cela coûte de l'espace de stockage et qu'il faut gérer la mise à jour de plusieurs entrées lors de la suppression ou de la modification d'un nœud dupliqué. Cependant, dans certains scénarios où les données ne sont pas souvent mises à jour, le fait d'avoir des relations bidirectionnelles pourrait faciliter considérablement le processus d'extraction / écriture.

Dans la plupart des scénarios où une requête SQL semble nécessaire, inverser les données et créer des relations bidirectionnelles est généralement la solution.

Considérez une application utilisant la base de données ci-dessus qui nécessite la possibilité de:

  1. Énumérez les cours suivis par un élève et ...
  2. Liste tous les étudiants dans un certain cours

Si la structure de la base de données avait été unidirectionnelle, il serait incroyablement plus lent d'analyser ou d'interroger l'une des deux exigences ci-dessus. Dans certains scénarios, la redondance rend les opérations fréquentes plus rapides et beaucoup plus efficaces, ce qui, à long terme, rend les doublons négligeables.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow