MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB (noSQL), wann Sammlungen geteilt werden sollen

Wie bereits geschrieben, gibt es für SQL keine Regeln wie die zweite Normalform.

Es gibt jedoch einige Best Practices und häufige Fallstricke im Zusammenhang mit der Optimierung für MongoDB, die ich hier auflisten werde.

Überbeanspruchung durch Einbettung

Die BSON-Grenze

Entgegen der landläufigen Meinung ist an Referenzen nichts auszusetzen. Angenommen, Sie haben eine Bibliothek mit Büchern und möchten die Ausleihen nachverfolgen. Sie könnten mit einem solchen Modell beginnen

{
  // We use ISBN for its uniqueness 
  _id: "9783453031456"
  title: "Schismatrix",
  author: "Bruce Sterling",
  rentals: [
    {
      name:"Markus Mahlberg,
      start:"2015-05-05T03:22:00Z",
      due:"2015-05-12T12:00:00Z"
    }
  ]
}

Es gibt zwar mehrere Probleme mit diesem Modell, aber das wichtigste ist nicht offensichtlich – es wird eine begrenzte Anzahl von Vermietungen geben aufgrund der Tatsache, dass BSON-Dokumente eine Größenbeschränkung von 16 MB haben.

Das Dokumentmigrationsproblem

Das andere Problem beim Speichern von Mieten in einem Array wäre, dass dies relativ häufige Dokumentenmigrationen verursachen würde, was ein ziemlich kostspieliger Vorgang ist. BSON-Dokumente werden niemals partitioniert und mit etwas zusätzlichem Speicherplatz erstellt, der im Voraus zugewiesen wird, wenn sie wachsen. Dieser zusätzliche Platz wird als Polsterung bezeichnet. Wenn die Auffüllung überschritten wird, wird das Dokument an eine andere Stelle in den Datendateien verschoben und neuer Auffüllungsraum wird zugewiesen. Daher führen häufige Hinzufügungen von Daten zu häufigen Dokumentmigrationen. Daher empfiehlt es sich, häufige Aktualisierungen zu verhindern, die die Größe des Dokuments erhöhen, und stattdessen Verweise zu verwenden.

Für das Beispiel würden wir also unser einzelnes Modell ändern und ein zweites erstellen. Zuerst das Modell für das Buch

{
  _id: "9783453031456",
  title:"Schismatrix",
  author: "Bruce Sterling"
}

Das zweite Modell für die Miete würde so aussehen

{
  _id: new ObjectId(),
  book: "9783453031456",
  rentee: "Markus Mahlberg",
  start: ISODate("2015-05-05T03:22:00Z"),
  due: ISODate("2015-05-05T12:00:00Z"),
  returned: ISODate("2015-05-05T11:59:59.999Z")
}

Derselbe Ansatz könnte natürlich auch für Autor oder Mieter verwendet werden.

Das Problem mit der Übernormalisierung

Blicken wir einige Zeit zurück. Ein Entwickler würde die an einem Business Case beteiligten Entitäten identifizieren, ihre Eigenschaften und Beziehungen definieren, die entsprechenden Entitätsklassen schreiben, seinen Kopf für ein paar Stunden gegen die Wand schlagen, um das dreifache Innen-Außen-oben-und-darüber-JOIN-Arbeiten zu bekommen, das erforderlich ist für den Anwendungsfall und alle lebten glücklich bis ans Ende ihrer Tage. Warum also NoSQL im Allgemeinen und MongoDB im Besonderen verwenden? Denn niemand lebte glücklich bis ans Ende seiner Tage. Dieser Ansatz skaliert fürchterlich und fast ausschließlich ist die einzige Skalierungsmöglichkeit vertikal.

Aber der Hauptunterschied von NoSQL besteht darin, dass Sie Ihre Daten gemäß den Fragen modellieren, die Sie beantworten müssen.

Schauen wir uns eine typische n:m-Beziehung an und nehmen als Beispiel die Beziehung von Autoren zu Büchern. In SQL hätten Sie drei Tabellen:zwei für Ihre Entitäten (Bücher und Autoren ) und eine für die Relation (Wer ist der Autor welchen Buches?). ). Natürlich könnten Sie diese Tabellen nehmen und ihre entsprechenden Sammlungen erstellen. Da es in MongoDB jedoch keine JOINs gibt, benötigen Sie drei Abfragen (eine für die erste Entität, eine für ihre Beziehungen und eine für die zugehörigen Entitäten), um die zugehörigen Dokumente einer Entität zu finden. Dies wäre nicht sinnvoll, da der Drei-Tabellen-Ansatz für n:m-Beziehungen speziell erfunden wurde, um die strengen Schemas zu überwinden, die SQL-Datenbanken erzwingen. Da MongoDB ein flexibles Schema hat, wäre die erste Frage, wo die Beziehung gespeichert werden soll, um die Probleme zu vermeiden die sich aus der Überbeanspruchung der Einbettung ergeben. Da ein Autor in den kommenden Jahren vielleicht noch einige Bücher schreiben wird, sich die Urheberschaft eines Buches aber selten, wenn überhaupt, ändert, ist die Antwort einfach:Wir speichern die Autoren als Verweis auf die Autoren in den Buchdaten

{
  _id: "9783453526723",
  title: "The Difference Engine",
  authors: ["idOfBruceSterling","idOfWilliamGibson"]
}

Und jetzt können wir die Autoren dieses Buches finden, indem wir zwei Abfragen durchführen:

var book = db.books.findOne({title:"The Difference Engine"})
var authors = db.authors.find({_id: {$in: book.authors})

Ich hoffe, das Obige hilft Ihnen bei der Entscheidung, wann Sie Ihre Sammlungen tatsächlich „aufteilen“ sollten, und um die häufigsten Fallstricke zu umgehen.

Schlussfolgerung

Was Ihre Fragen betrifft, hier sind meine Antworten

  1. Wie bereits geschrieben:Nein , aber wenn Sie die technischen Einschränkungen im Auge behalten, sollten Sie eine Vorstellung davon bekommen, wann es sinnvoll sein könnte.
  2. Es ist nicht schlecht – solange es zu Ihrem/Ihren Anwendungsfall(en) passt . Wenn Sie eine bestimmte Kategorie und ihre _id haben , es ist einfach, die verwandten Produkte zu finden. Wenn Sie das Produkt laden, können Sie die Kategorien, zu denen es gehört, einfach und effizient als _id abrufen ist standardmäßig indiziert.
  3. Ich habe noch keinen Anwendungsfall gefunden, der mit MongoDB nicht bewerkstelligt werden kann, obwohl einige Dinge mit MongoDB etwas komplizierter werden können. Was Sie imho tun sollten, ist, die Summe Ihrer funktionalen und nicht funktionalen Anforderungen zu nehmen und zu prüfen, ob die Vorteile die Nachteile überwiegen. Meine Faustregel:Wenn „Skalierbarkeit“ oder „Hochverfügbarkeit/automatisches Failover“ auf Ihrer Anforderungsliste stehen, ist MongoDB mehr als einen Blick wert.