Szukaj…


Wprowadzenie

Baza danych Firebase to baza danych NoSQL, która przechowuje swoje dane w postaci hierarchicznych obiektów JSON. Nie ma żadnych tabel ani rekordów w jakiejkolwiek formie, jaką normalnie posiadałaby baza danych SQL, tylko węzły tworzące strukturę klucz-wartość.

Normalizacja danych

Aby mieć właściwie zaprojektowaną strukturę bazy danych, wymagania dotyczące danych muszą być dokładnie określone i przemyślane. Struktura w tym przypadku powinna zostać znormalizowana; im bardziej płaskie drzewo JSON, tym szybszy dostęp do danych.

Za I przeciw

Zły kierunek

Rozważ następującą 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
  }
}

To świetny przykład tego, czego NIE należy robić. Struktury wielo zagnieżdżone, takie jak powyższa, mogą być bardzo problematyczne i mogą powodować ogromne pogorszenie wydajności.

Sposób, w jaki Firebase uzyskuje dostęp do węzła, polega na pobraniu wszystkich danych dzieci, a następnie iteracji po wszystkich węzłach tego samego poziomu (dzieci wszystkich rodziców). Teraz wyobraź sobie bazę danych z kilkoma użytkownikami , z których każdy ma setki (a nawet tysiące) postów . Dostęp do postu w tym przypadku może potencjalnie załadować setki megabajtów nieużywanych danych. W bardziej skomplikowanej aplikacji zagnieżdżanie może być głębsze niż tylko 4 warstwy, co spowodowałoby więcej bezużytecznych pobrań i iteracji.

Właściwy sposób

Spłaszczenie tej samej struktury wyglądałoby tak

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

Oszczędza to ogromnego nakładu pracy, iterując mniejszą liczbę węzłów, aby uzyskać dostęp do obiektu docelowego. Wszyscy użytkownicy , którzy nie mają żadnych postów, nie będą istnieć w gałęzi postów , więc iteracja nad tymi użytkownikami w niewłaściwy sposób powyżej jest całkowicie bezużyteczna.

Relacje dwukierunkowe

Poniżej znajduje się przykład prostej i minimalnej bazy danych uczelni, która wykorzystuje dwustronne relacje

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

Pamiętaj, że każdy uczeń ma listę kursów i każdy kurs ma listę zapisanych studentów .

Redundancja nie zawsze jest złym podejściem. Prawdą jest, że to kosztuje przestrzeń dyskową i konieczność radzenia sobie z aktualizacją wielu wpisów podczas usuwania lub edycji zduplikowanego węzła; jednak w niektórych scenariuszach, w których dane nie są często aktualizowane, wzajemne relacje mogą znacznie ułatwić proces pobierania / zapisywania.

W większości scenariuszy, w których wydaje się potrzebne zapytanie podobne do SQL, zwykle rozwiązaniem jest odwrócenie danych i utworzenie dwustronnych relacji.

Rozważ aplikację korzystającą z powyższej bazy danych, która wymaga umiejętności:

  1. Wymień kursy, które bierze dany uczeń i ...
  2. Wymień wszystkich uczniów na danym kursie

Gdyby struktura bazy danych była jednokierunkowa, skanowanie lub wyszukiwanie jednego z dwóch powyższych wymagań byłoby znacznie wolniejsze. W niektórych scenariuszach nadmiarowość sprawia, że częste operacje są szybsze i znacznie wydajniejsze, co w dłuższej perspektywie sprawia, że koszt duplikacji jest znikomy.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow