Suche…


Einführung

Die Firebase-Datenbank ist eine NoSQL-Datenbank, in der ihre Daten in Form von hierarchischen JSON-Objekten gespeichert werden. Es gibt keine Tabellen oder Datensätze in irgendeiner Form, wie es normalerweise eine SQL-Datenbank hätte, nur Knoten, die eine Schlüsselwertstruktur bilden.

Datennormierung

Um eine ordnungsgemäß ausgelegte Datenbankstruktur zu haben, müssen die Datenanforderungen gründlich umrissen und vorausgedacht werden. Die Struktur sollte in diesem Fall normalisiert werden. Je flacher der JSON-Baum ist, desto schneller ist der Datenzugriff.

Verhaltensregeln

Der falsche Weg

Betrachten Sie die folgende Struktur

{
  "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
  }
}

Dies ist ein großartiges Beispiel dafür, was Sie NICHT tun sollten. Multi-geschachtelte Strukturen wie die oben genannten können sehr problematisch sein und einen erheblichen Performance-Rückschlag verursachen.

Firebase greift auf einen Knoten zu, indem alle Daten der Kinder heruntergeladen und anschließend über alle Knoten derselben Ebene (alle Kinder der Eltern) iteriert werden. Stellen Sie sich nun eine Datenbank mit mehreren Benutzern vor , von denen jeder Hunderte (oder sogar Tausende) von Beiträgen hat . Durch den Zugriff auf einen Beitrag könnten in diesem Fall möglicherweise Hunderte von Megabytes nicht verwendeter Daten geladen werden. In einer komplizierteren Anwendung könnte die Verschachtelung tiefer als nur 4 Ebenen sein, was zu mehr nutzlosen Downloads und Iterationen führen würde.

Der richtige Weg

Eine Abflachung der gleichen Struktur würde so aussehen

{
  // "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
  }
}

Dies erspart viel Overhead, da weniger Knoten für den Zugriff auf ein Zielobjekt iteriert werden. Alle Benutzer , die über keine Posts verfügen, sind nicht im Posts- Zweig vorhanden. Daher ist es völlig sinnlos, diese Benutzer auf die falsche Weise zu durchlaufen.

Wechselseitige Beziehungen

Das folgende Beispiel zeigt eine einfache und minimale College-Datenbank, die bidirektionale Beziehungen verwendet

{
  "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
  }
}

Beachten Sie, dass jeder Student eine Liste mit Kursen hat und jeder Kurs eine Liste mit eingeschriebenen Studenten hat .

Redundanz ist nicht immer ein schlechter Ansatz. Es ist richtig, dass dies Speicherplatz kostet und dass beim Aktualisieren mehrerer Einträge beim Löschen oder Bearbeiten eines duplizierten Knotens mehrere Updates vorgenommen werden müssen. In einigen Szenarien, in denen Daten nicht häufig aktualisiert werden, kann eine Zwei-Wege-Beziehung den Abruf- / Schreibvorgang erheblich erleichtern.

In den meisten Szenarien, in denen eine SQL-ähnliche Abfrage erforderlich erscheint, ist das Invertieren der Daten und das Erstellen von bidirektionalen Beziehungen normalerweise die Lösung.

Betrachten Sie eine Anwendung, die die Datenbank oben verwendet, für die Folgendes erforderlich ist:

  1. Listen Sie die Kurse auf, die ein bestimmter Student nimmt und ...
  2. Listen Sie alle Schüler in einem bestimmten Kurs auf

Wenn die Datenbankstruktur einseitig gerichtet gewesen wäre, wäre das Scannen oder Abfragen nach einer der beiden oben genannten Anforderungen enorm langsamer. In einigen Szenarien macht die Redundanz häufige Vorgänge schneller und effizienter, was die Kosten der Duplikationen auf lange Sicht vernachlässigbar macht.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow