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

Planen und Verwalten von Schemas in MongoDB (auch wenn es schemalos ist)

Als MongoDB eingeführt wurde, war das Hauptmerkmal, das hervorgehoben wurde, seine Fähigkeit, „schemalos“ zu sein. Was bedeutet das? Das bedeutet, dass man JSON-Dokumente mit jeweils unterschiedlicher Struktur in derselben Sammlung speichern kann. Das ist ziemlich cool. Das Problem beginnt jedoch, wenn Sie die Dokumente abrufen müssen. Wie erkennen Sie, dass ein abgerufenes Dokument eine bestimmte Struktur hat oder ob es ein bestimmtes Feld enthält oder nicht? Sie müssen alle Dokumente durchgehen und nach diesem bestimmten Feld suchen. Aus diesem Grund ist es sinnvoll, das MongoDB-Schema sorgfältig zu planen, insbesondere für große Anwendungen.

Bei MongoDB gibt es keine spezifische Möglichkeit, das Schema zu entwerfen. Es hängt alles von Ihrer Anwendung ab und davon, wie Ihre Anwendung die Daten verwenden wird. Es gibt jedoch einige gängige Vorgehensweisen, die Sie beim Entwerfen Ihres Datenbankschemas befolgen können. Hier werde ich diese Praktiken und ihre Vor- und Nachteile diskutieren.

One-to-Few-Modellierung (Einbettung)

Dieses Design ist ein sehr gutes Beispiel für das Einbetten von Dokumenten. Betrachten Sie dieses Beispiel einer Personensammlung, um diese Modellierung zu veranschaulichen.

{
  name: "Amy Cooper",
  hometown: "Seoul",
  addresses: [
    { city: 'New York', state: 'NY', cc: 'USA' },
    { city: 'Jersey City', state: 'NJ', cc: 'USA' }
  ]
}

Vorteile:

  • Sie können alle Informationen in einer einzigen Abfrage erhalten.

Nachteile:

  • Eingebettete Daten sind vollständig vom übergeordneten Dokument abhängig. Sie können die eingebetteten Daten nicht unabhängig durchsuchen.
  • Betrachten Sie das Beispiel, in dem Sie mit diesem Ansatz ein Aufgabenverfolgungssystem erstellen. Anschließend betten Sie alle personenspezifischen Aufgaben in die Personensammlung ein. Wenn Sie eine Abfrage auslösen möchten wie:Zeig mir alle Aufgaben, die morgen als Deadline haben. Dies kann sehr schwierig sein, obwohl es sich um eine einfache Abfrage handelt. In diesem Fall sollten Sie andere Ansätze in Betracht ziehen.

One-to-Many-Modellierung (Referenzierung)

Bei dieser Art der Modellierung enthält das übergeordnete Dokument die Referenz-ID (ObjectID) der untergeordneten Dokumente. Sie müssen Verknüpfungen auf Anwendungsebene verwenden (Kombinieren von zwei Dokumenten nach dem Abrufen aus der Datenbank auf Anwendungsebene), um Dokumente abzurufen, also keine Verknüpfungen auf Datenbankebene. Daher wird die Belastung einer Datenbank reduziert. Betrachten Sie dieses Beispiel:

// Parts collection
{
  _id: ObjectID(1234),
  partno: '1',
  name: ‘Intel 100 Ghz CPU',
  qty: 100,
  cost: 1000,
  price: 1050
}
// Products collection
{
  name: 'Computer WQ-1020',
  manufacturer: 'ABC Company',
  catalog_number: 1234,
  parts: [
    ObjectID(‘1234’), <- Ref. for Part No: 1
    ObjectID('2345'),
    ObjectID('3456')
  ]
}

Angenommen, jedem Produkt können mehrere tausend Teile zugeordnet sein. Für diese Art von Datenbanken ist die Referenzierung die ideale Art der Modellierung. Sie geben die Referenz-IDs aller zugehörigen Teile unter Produktdokument ein. Dann können Sie Verknüpfungen auf Anwendungsebene verwenden, um die Teile für ein bestimmtes Produkt zu erhalten.

Vorteile:

  • Bei dieser Art der Modellierung ist jedes Teil ein separates Dokument, sodass Sie alle teilebezogenen Abfragen auf diese Dokumente anwenden können. Keine Abhängigkeit vom übergeordneten Dokument.
  • Sehr einfach durchzuführende CRUD-Operationen (Create, Read, Update, Write) für jedes Dokument unabhängig voneinander.

Nachteile:

  • Ein großer Nachteil bei dieser Methode ist, dass Sie eine zusätzliche Abfrage durchführen müssen, um die Teiledetails zu erhalten. Damit Sie Verknüpfungen auf Anwendungsebene mit dem Produktdokument durchführen können, um die erforderliche Ergebnismenge zu erhalten. Es kann also zu einem Abfall der DB-Leistung führen.
Multiplenines Become a MongoDB DBA – Bringing MongoDB to ProductionErfahren Sie, was Sie wissen müssen, um MongoDBDownload for Free bereitzustellen, zu überwachen, zu verwalten und zu skalieren

Eins-zu-Millionen-Modellierung (übergeordnete Referenzierung)

Wenn Sie in jedem Dokument Tonnen von Daten speichern müssen, können Sie keinen der oben genannten Ansätze verwenden, da MongoDB eine Größenbeschränkung von 16 MB pro Dokument hat. Ein perfektes Beispiel für diese Art von Szenario kann ein Ereignisprotokollierungssystem sein, das Protokolle von verschiedenen Maschinentypen sammelt und sie in Protokoll- und Maschinensammlungen speichert.

Hier können Sie nicht einmal daran denken, den Embedding-Ansatz zu verwenden, der alle Protokollinformationen für eine bestimmte Maschine in einem einzigen Dokument speichert. Dies liegt daran, dass die Dokumentgröße in nur wenigen Stunden mehr als 16 MB betragen wird. Selbst wenn Sie nur die Referenz-IDs aller Protokolldokumente speichern, werden Sie dennoch die 16-MB-Grenze ausschöpfen, da einige Computer an einem einzigen Tag Millionen von Protokollnachrichten generieren können.

In diesem Fall können wir also den Parent-Referencing-Ansatz verwenden. Anstatt Referenz-IDs von untergeordneten Dokumenten im übergeordneten Dokument zu speichern, speichern wir bei diesem Ansatz die Referenz-ID des übergeordneten Dokuments in allen untergeordneten Dokumenten. In unserem Beispiel speichern wir also die ObjectID der Maschine in Protokolldokumenten. Betrachten Sie dieses Beispiel:

// Machines collection
{
  _id : ObjectID('AAA'),
  name : 'mydb.example.com',
  ipaddr : '127.66.0.4'
}
// Logs collection
{
  time : ISODate("2015-09-02T09:10:09.032Z"),
  message : 'WARNING: CPU usage is critical!',
  host: ObjectID('AAA')       -> references Machine document
}

Angenommen, Sie möchten die letzten 3000 Protokolle von Maschine 127.66.0.4 finden:

machine = db.machines.findOne({ipaddr : '127.66.0.4'});
msgs = db.logmsg.find({machine: machine._id}).sort({time : -1}).limit(3000).toArray()

Zwei-Wege-Referenzierung

Bei diesem Ansatz speichern wir die Referenzen auf beiden Seiten, was bedeutet, dass die Referenz des Elternteils im untergeordneten Dokument und die Referenz des Kindes im übergeordneten Dokument gespeichert wird. Dies macht die Suche in One-to-Many-Modellierungen relativ einfach. Beispielsweise können wir sowohl übergeordnete als auch Aufgabendokumente durchsuchen. Andererseits erfordert dieser Ansatz zwei separate Abfragen, um ein Dokument zu aktualisieren.

// person
{
  _id: ObjectID("AAAA"),
  name: "Bear",
  tasks [ 
    ObjectID("AAAD"),
    ObjectID("ABCD"), -> Reference of child document
    ObjectID("AAAB")
  ]
}
// tasks
{
  _id: ObjectID("ABCD"),
  description: "Read a Novel",
  due_date:  ISODate("2015-11-01"),
  owner: ObjectID("AAAA") -> Reference of parent document
}

Schlussfolgerung

Am Ende hängt alles von Ihren Anwendungsanforderungen ab. Sie können das MongoDB-Schema so gestalten, dass es für Ihre Anwendung am vorteilhaftesten ist und Ihnen eine hohe Leistung bietet. Hier sind einige zusammengefasste Überlegungen, die Sie beim Entwerfen Ihres Schemas berücksichtigen können.

  1. Entwerfen Sie das Schema basierend auf den Datenzugriffsmustern Ihrer Anwendung.
  2. Es ist nicht notwendig, jedes Mal Dokumente einzubetten. Kombinieren Sie Dokumente nur, wenn Sie sie zusammen verwenden werden.
  3. Erwägen Sie die Duplizierung von Daten, da Speicherplatz heutzutage billiger ist als Rechenleistung.
  4. Optimieren Sie das Schema für häufigere Anwendungsfälle.
  5. Arrays sollten nicht außerhalb der Grenzen wachsen. Wenn es mehr als ein paar hundert untergeordnete Dokumente gibt, betten Sie sie nicht ein.
  6. Bevorzugen Sie Joins auf Anwendungsebene gegenüber Joins auf Datenbankebene. Mit der richtigen Indizierung und der richtigen Verwendung von Projektionsfeldern können Sie viel Zeit sparen.