Datenmodellierung

Das Datenmodellierungsdokument ist das erste Best-Practice-Dokument in der Reihe. Es zeigt Ihnen die folgenden bewährten Verfahren:

  • Was Sie über Ihre APIs wissen müssen.
  • So modellieren Sie Ihre Daten.
  • Die Größe der Dokumente, die Sie verwenden müssen
  • Was Sie vermeiden sollten.
  • Vorgehensweise zum Konfigurieren Ihrer Datenbanken.

Weitere Informationen finden Sie unter Indexierung und Abfrage oder IBM Cloudant in der Praxis.

Der Inhalt dieses Dokuments wurde ursprünglich von Stefan Kruger als Blogbeitrag Best Practice und Worst Practice am 21. November 2019 geschrieben.

Verstehen Sie die API, auf die Sie abzielen

Sie können Java™, Python, Gooder Node.js oder eine andere anwendungsfallspezifische Sprache oder Plattform verwenden. Eine dieser Sprachen wird wahrscheinlich mit komfortablen clientseitigen Bibliotheken geliefert, die den Zugriff auf IBM Cloudant unter Berücksichtigung der Konventionen, die Sie für Ihre Tools erwarten, gut integrieren. Diese Sprachen sind hervorragend für die Programmierereffizienz, aber sie verbergen auch die API aus der Ansicht.

Diese Abstraktion ist, was Sie wollen, der ganze Grund für die Verwendung einer Client-Bibliothek ist es, sich wiederholte, mühsame Kesselplattierung zu speichern. Sie müssen jedoch die zugrunde liegende API verstehen, wenn Sie Probleme beheben und melden. Wenn Sie ein mutmaßliches Problem an IBM Cloudantmelden, hilft es uns, Ihnen zu helfen, wenn Sie uns eine Möglichkeit bieten, das Problem zu reproduzieren.

Diese Anforderung bedeutet nicht das Ausschneiden und Einfügen eines heftigen Blocks der Java™-Quelle Ihrer Anwendung in ein Support-Ticket, da es wahrscheinlich nicht erstellt werden kann. Außerdem führt Ihr clientseitiger Code Unsicherheiten darüber ein, wo das Problem sein könnte, Ihre Seite oder unsere Seite?

Stattdessen fordern die IBM CloudantSupport-Teams in der Regel die Gruppe von API-Aufrufen an, idealerweise als Gruppe von curl-Befehlen, die sie ausführen können und die das Problem veranschaulichen. Wenn Sie diesen Ansatz zur Fehlerbehebung in der Regel verwenden, können Sie auch einfacher ermitteln, wo Probleme fehlschlagen. Wenn sich Ihr Code unerwartet verhält, versuchen Sie, das Problem zu reproduzieren, indem Sie nur direkten Zugriff auf die API verwenden.

Wenn dies nicht möglich ist, liegt das Problem nicht beim IBM Cloudant-Service selbst.

Wenn Sie ein Leistungsproblem untersuchen, ziehen Sie die Protokolle zu Rate, die von IBM Cloud®bereitgestellt werden. Wenn die Protokolle zeigen, dass Ihre Anforderungen von IBM Cloudantschnell verarbeitet werden, Ihre Anwendung jedoch langsam ist, liegt die Ursache dieses Problems bei Ihrem clientseitigen Anwendungscode. Siehe die Regel zur Protokollierung und Überwachung.

Wenn Sie vermuten, dass ein Problem mit einer offiziell unterstützten Clientbibliothek zusammenliegt, versuchen Sie, ein kleines, eigenständiges Codebeispiel zu erstellen, das das Problem veranschaulicht. Verwenden Sie in diesem eigenständigen Codebeispiel möglichst wenige andere Abhängigkeiten. Wenn Sie Java™verwenden, ist es uns hilfreich, wenn Sie einen minimalen Testharness verwenden können, um Bibliotheksprobleme hervorzuheben.

Gelegentlich empfängt IBM Cloudant Support-Tickets, in denen angegeben wird, dass "IBM Cloudant defekt ist, weil meine Anwendung langsam ist", ohne viele unterstützende Beweise. Fast immer kann dieser Fall auf Probleme im Anwendungscode auf der Clientseite oder auf Missverständnisse bezüglich der Funktionsweise von IBM Cloudant zurückgeführt werden.

Nicht immer, aber fast immer.

Wenn Sie die API besser verstehen, gewinnen Sie auch Erfahrung mit dem Verhalten von IBM Cloudant, insbesondere in Bezug auf die Leistung. Wenn Sie eine Client-Bibliothek verwenden, müssen Sie zumindest wissen, wie Sie herausfinden können, welche HTTP Anfragen durch einen bestimmten Funktionsaufruf erzeugt werden. Weitere Informationen finden Sie auf den folgenden Websites:

Dokumente müssen Daten gruppieren, die sich meistens zusammen ändern

Wenn Sie mit der Modellierung Ihrer Daten beginnen, haben Sie früher oder später das Problem, wie Ihre Dokumente strukturiert sein könnten. Jetzt wissen Sie, dass IBM Cloudant keine Normalisierung durchsetzt und dass es keine Transaktionen des Typs gibt, von dem Sie gewohnt sind, zum Beispiel Postgres. Die Versuchung kann groß sein, so viel wie möglich in jedes Dokument zu packen, was auch zu Einsparungen bei der Nutzung von HTTP führen würde.

Diese Praxis ist oft eine schlechte Idee.

Wenn Ihr Modell Informationen gruppiert, die nicht zusammen geändert werden, ist es wahrscheinlicher, dass Aktualisierungskonflikte auftreten.

Stellen Sie sich eine Situation vor, in der Sie Benutzer haben, denen jeweils eine Gruppe von Bestellungen zugeordnet ist. Eine Möglichkeit wäre, die Aufträge als Array im Benutzerdokument darzustellen:

{ // DON'T DO THIS
  "customer_id": 65522389,
  "orders": [
    {
      "order_id": 887865,
      "items": [
        {
          "item_id": 9982,
          "item_name": "Iron sprocket",
          "cost": 53.0
        },
        {
          "item_id": 2932,
          "item_name": "Rubber wedge",
          "cost": 3.0
        }
      ]
    }
  ]
}

Um einen Auftrag hinzuzufügen, muss ich das vollständige Dokument abrufen, das JSON-Unmarshalling durchführen, das Element hinzufügen, das neue JSON-Marshalling ausführen und als Aktualisierung zurücksenden. Wenn ich der Einzige bin, der es tut, könnte es für eine Weile funktionieren. Wenn das Dokument gleichzeitig aktualisiert oder repliziert wird, können Aktualisierungskonflikte auftreten.

Verwenden Sie stattdessen separate Bestellungen als eigenen Dokumenttyp und verweisen Sie auf die Kunden-ID. Jetzt ist das Modell unveränderlich. Zum Hinzufügen eines Auftrags erstellen Sie ein neues Auftragsdokument in der Datenbank, das keine Konflikte generieren kann.

Um alle Bestellungen für einen bestimmten Kunden abrufen zu können, können wir eine Ansicht verwenden, die wir später abdecken.

Vermeiden Sie Konstrukte, die nach Möglichkeit auf Aktualisierungen von Teilen vorhandener Dokumente angewiesen sind. Schlechte Datenmodelle sind oft schwer zu ändern, wenn Sie in der Produktion sind.

Das vorherige Muster kann effizient gelöst werden, indem partitionierte Datenbanken verwendet werden, die später ausführlicher behandelt werden.

Weitere Informationen finden Sie in der folgenden Dokumentation:

Dokumente klein halten

IBM Cloudant legt eine maximale Dokumentgröße von 1 MB fest. Dieser Grenzwert bedeutet nicht, dass eine Dokumentgröße von close-to-1-MB eine gute Idee ist. Im Gegenteil, wenn Sie feststellen, dass Sie Dokumente erstellen, die die einstellige KB überschreiten, müssen Sie wahrscheinlich Ihr Modell erneut aufrufen. Mehrere Dinge in IBM Cloudant werden weniger leistungsfähig, wenn Dokumente wachsen. Die JSON-Decodierung ist beispielsweise kostenintensiv.

Betrachten wir die folgenden Abschnitte: Dokumente müssen Daten gruppieren, die sich größtenteils ändern und Dokumente klein halten. Es ist hervorzuheben, dass Modelle, die auf Updates angewiesen sind, eine maximale Volumenbegrenzung von 1 MB haben, die Grenze für die Dokumentgröße. Diese Größe ist nicht, was Sie wollen.

Verwendung von Anhängen vermeiden

IBM Cloudant unterstützt das Speichern von Anhängen neben Dokumenten, ein langjähriges Feature, das es von CouchDBübernimmt. Wenn Sie IBM Cloudant als Back-End für eine Webanwendung verwenden, können Sie auch kleine Symbole und andere statische Assets wie CSS und JavaScript-Dateien mit den Daten speichern.

Bevor Sie Anhänge in IBM Cloudant verwenden, müssen Sie einige Punkte berücksichtigen, insbesondere wenn Sie größere Assets wie Bilder und Videos betrachten:

  1. IBM Cloudant ist als Blockspeicher kostenintensiv.
  2. Die interne Implementierung von IBM Cloudantist bei der Verarbeitung großer Mengen binärer Daten nicht effizient.

Langsam und teuer.

IBM Cloudant ist für kleine Assets und gelegentliche Verwendung akzeptabel. Wenn Sie Binärdaten neben IBM Cloudant-Dokumenten speichern müssen, ist es in der Regel besser, eine separate Lösung zu verwenden, die für diesen Zweck besser geeignet ist. Sie müssen nur die Metadaten des Anhangs im Dokument IBM Cloudant speichern. Ja, das bedeutet, dass Sie zusätzlichen Code schreiben müssen, um den Anhang in einen geeigneten Blockspeicher Ihrer Wahl hochzuladen. Vergewissern Sie sich, dass dies gelungen ist, bevor Sie das Token oder URL zum Anhang im Dokument IBM Cloudant speichern.

Ihre Datenbanken sind kleiner, billiger, schneller und einfacher zu replizieren. Weitere Informationen finden Sie auf den folgenden Websites:

Weniger Datenbanken sind besser als viele

Falls möglich, begrenzen Sie die Anzahl der Datenbanken pro IBM Cloudant-Konto auf maximal 500. Diese Zahl ist zwar keine magische Zahl (IBM Cloudant kann sicher mehr verarbeiten), es gibt jedoch mehrere Anwendungsfälle, die durch eine große Anzahl von Datenbanken in einem Konto beeinträchtigt werden.

Der Replikatorscheduler verfügt über eine begrenzte Anzahl gleichzeitiger Replikationsjobs, für deren Ausführung er vorbereitet ist. Wenn die Anzahl der Datenbanken zunimmt, erhöht sich die Replikationslatenz wahrscheinlich, wenn Sie versuchen, alles in einem Konto enthaltene zu replizieren.

Die Kehrseite derselben Münze ist der operative Aspekt: IBM CloudantDas Betriebsteam verlässt sich auch auf die Replikation, um sich um Konten zu bewegen. Indem Sie die Anzahl der Datenbanken reduzieren, helfen Sie uns, Ihnen zu helfen, wenn Sie Ihr Konto von einem Standort an einen anderen verlagern müssen.

Wann müssen Sie also eine einzelne Datenbank verwenden und mithilfe von Ansichten zwischen verschiedenen Dokumenttypen unterscheiden und wann müssen Sie mehrere Datenbanken verwenden, um Ihre Daten zu modellieren? IBM Cloudant kann Ansichten nicht datenbankübergreifend einbinden. Wenn Sie nicht zusammengehörige Daten haben, die nie miteinander verknüpft oder abgefragt werden können, können diese Daten ein Kandidat für die Aufteilung auf mehrere Datenbanken sein.

Wenn Sie ein ständig wachsendes Dataset haben (wie ein Protokoll, Sensormesswerte oder andere Arten von Zeitreihen), ist es auch keine gute Idee, eine einzige, immer größer werdende, massive Datenbank zu erstellen. Für diese Art von Anwendungsfall ist ein Time-Box-Verfahren erforderlich, auf das später noch näher eingegangen wird.

Vermeiden Sie die Datenbank pro Benutzer Anti-Muster wie die Pest

Wenn Sie einen Multi-User-Service auf IBM Cloudanterstellen, ist es verlockend, dass jeder Benutzer seine Daten in einer separaten Datenbank unter dem Anwendungskonto speichert. Das funktioniert gut, vor allem, wenn die Anzahl der Benutzer ist klein.

Fügen Sie jetzt die Notwendigkeit hinzu, benutzerübergreifende Analysen abzuleiten. Sie können dies tun, indem Sie alle Benutzerdatenbanken in eine einzige Analysedatenbank replizieren. Alles gut. Diese App ist plötzlich erfolgreich geworden, und die Anzahl der Benutzer wuchs im Bereich von 150-20.000. Sie haben 20.000 Replikationen, um die Analysedatenbank auf dem neuesten Stand zu halten. Wenn Sie auch in einer Aktiv/Aktiv-Disaster-Recovery-Konfiguration ausführen möchten, fügen Sie weitere 20.000 Replikationen hinzu und das System funktioniert nicht mehr.

Stattdessen Multiplex-Benutzerdaten in weniger Datenbanken oder Shard-Benutzer in eine Gruppe von Datenbanken und/oder Konten. Auf diese Weise müssen Sie keine Replikation durchführen, um eine Analysedatenbank bereitzustellen, aber die Authentifizierung wird komplizierter, da IBM Cloudant nur die Authentifizierung auf Datenbankebene bereitstellt.

Es ist erwähnenswert, dass der Ansatz "Datenbank pro Benutzer" verlockend ist, weil IBM Cloudant-Berechtigungen "pro Datenbank" sind, aber es ist nicht wirklich der Fehler des Benutzers, dass dieses Muster entstanden ist.

Schreiben angepasster JavaScript-Reduce-Funktionen vermeiden

Die MapReduce-Ansichten in IBM Cloudant sind großartig. Aber mit großer Macht kommt große Verantwortung. Der Mapteil einer MapReduce-Sicht wird inkrementell erstellt, sodass sich der schockierende Code in der Map nur auf die Indexierungszeit und nicht auf die Abfragezeit auswirkt. Der Reduce-Part wird leider zur Abfragezeit ausgeführt. IBM Cloudant stellt eine Gruppe integrierter Reduce-Funktionen bereit, die intern in Erlangimplementiert sind. Diese Funktionen sind im richtigen Maß leistungsfähig, während Ihre handgefertigte JavaScript-Reduzierung dies nicht ist.

Wenn Sie feststellen, dass Sie Reduce-Funktionen schreiben, stoppen Sie und überlegen Sie, ob Sie Ihre Daten reorganisieren können, damit das Schreiben von Reduce-Funktionen nicht erforderlich ist. Oder damit Sie sich auf die eingebauten Reduzierstücke verlassen können.

Ansichten für partitionierte Datenbanken unterstützen keine benutzerdefinierten Verringerungen. Dies ist ein Faktor, der zu den signifikanten schnelleren Abfragen beiträgt, die nur solche Ansichten bieten können.

Weitere Informationen finden Sie in der IBM Cloudant-Dokumentation zu Reduziert.

Verwenden Sie zeitgepackte Datenbanken für immer größer werdende Datasets.

In der Regel ist es keine gute Idee, eine ständig wachsende Datenbank in IBM Cloudantzu haben. Große Datenbanken können schwierig zu sichern sein, erfordern ein erneutes Sharding, um eine gute Leistung zu erhalten, wenn sie wachsen, und leiden unter langen Indexerstellungszeiten.

Eine Möglichkeit, dieses Problem zu mindern, besteht darin, mehrere kleinere Datenbanken zu haben, mit einem gemeinsamen Muster, das Datenbanken mit Zeitfensterist: Ein großes Dataset wird in kleinere Datenbanken aufgeteilt, die jeweils ein Zeitfenster darstellen, z. B. einen Monat.

  • orders_2019_01
  • orders_2019_02
  • orders_2019_02

Neue Daten werden in die Datenbank dieses Monats geschrieben und Abfragen für Langzeitdaten können an die Datenbanken früherer Monate übertragen werden. Wenn die Daten eines Monats nicht mehr von Interesse sind, können sie in Object Storagearchiviert, die monatliche IBM Cloudant-Datenbank gelöscht und der Plattenspeicherplatz wiederhergestellt werden. Weitere Informationen finden Sie auf der folgenden Website.