Ricerca…


introduzione

Il database Firebase è un database NoSQL che memorizza i suoi dati sotto forma di oggetti JSON gerarchici. Non ci sono tabelle o record di qualsiasi forma come normalmente dovrebbe avere un database SQL, solo nodi che costituiscono una struttura di valori-chiave.

Normalizzazione dei dati

Per avere una struttura di database correttamente progettata, i requisiti dei dati devono essere accuratamente delineati e preveggenti. La struttura in questo caso dovrebbe essere normalizzata; più piatto è l'albero JSON, più veloce è l'accesso ai dati.

Cosa fare e cosa non fare

La strada sbagliata

Considera la seguente struttura

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

Questo è un ottimo esempio di cosa NON fare. Strutture multi-nidificate come quella sopra possono essere molto problematiche e causare un enorme calo delle prestazioni.

Il modo in cui Firebase accede a un nodo è il download di tutti i dati dei bambini, quindi l'iterazione su tutti i nodi dello stesso livello (i figli di tutti i genitori). Ora immagina un database con diversi utenti , ognuno con centinaia (o anche migliaia) di post . L'accesso a un post in questo caso potrebbe potenzialmente caricare centinaia di megabyte di dati inutilizzati. In un'applicazione più complicata, il nesting potrebbe essere più profondo di solo 4 livelli, il che comporterebbe download e iterazioni più inutili.

Il modo giusto

Appiattire la stessa struttura sarebbe come questo

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

Ciò risparmia una quantità enorme di overhead iterando su meno nodi per accedere a un oggetto target. Tutti gli utenti che non hanno alcun post non esisterebbero nel ramo dei post e quindi iterare sopra quegli utenti nel modo sbagliato sopra è completamente inutile.

Relazioni a due vie

Quello che segue è un esempio di un database college semplice e minimale che utilizza relazioni a due vie

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

Nota che ogni studente ha un elenco di corsi e ogni corso ha un elenco di studenti iscritti.

La ridondanza non è sempre un approccio sbagliato. È vero che costa lo spazio di archiviazione e deve gestire l'aggiornamento di più voci durante l'eliminazione o la modifica di un nodo duplicato; tuttavia, in alcuni scenari in cui i dati non vengono aggiornati spesso, la presenza di relazioni a due vie potrebbe facilitare notevolmente il processo di recupero / scrittura.

Nella maggior parte degli scenari in cui sembra necessaria una query simile a SQL, l'inversione dei dati e la creazione di relazioni bidirezionali sono solitamente la soluzione.

Prendi in considerazione un'applicazione che utilizza il database precedente che richiede la capacità di:

  1. Elenca i corsi che un certo studente sta prendendo e ...
  2. Elenca tutti gli studenti in un certo corso

Se la struttura del database fosse stata unidirezionale, sarebbe stato incredibilmente più lento scansionare o interrogare per uno dei due requisiti precedenti. In alcuni scenari, la ridondanza rende le operazioni frequenti più veloci e molto più efficienti che, a lungo termine, riducono il costo delle duplicazioni.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow