Messenger-Datenbank (Teil 1): Entwerfen des Basis-Frameworks

Wie Sie Geschäftsanforderungen in spezifische Datenstrukturen übersetzen können, am Beispiel des Entwurfs einer Messenger-Datenbank von Grund auf.

Messenger-Datenbank (Teil 1): Entwerfen des Basis-Frameworks
Unsere Basis wird nicht so groß und verteilt sein, wie VKontakte oder Badoo, aber „so dass es war“, aber es war gut – funktional, schnell und passen auf einen Server PostgreSQL – damit Sie beispielsweise irgendwo nebenbei eine separate Instanz des Dienstes bereitstellen können.

Daher werden wir nicht auf die Themen Sharding, Replikation und geoverteilte Systeme eingehen, sondern uns auf Schaltungslösungen innerhalb der Datenbank konzentrieren.

Schritt 1: Einige geschäftliche Besonderheiten

Wir werden unsere Botschaften nicht abstrakt gestalten, sondern in die Umgebung integrieren soziales Unternehmensnetzwerk. Das heißt, unsere Mitarbeiter korrespondieren nicht „nur“, sondern kommunizieren miteinander im Rahmen der Lösung bestimmter Geschäftsprobleme.

Und was sind die Aufgaben eines Unternehmens? Schauen wir uns das Beispiel von Vasily an, dem Leiter der Entwicklungsabteilung.

  • „Nikolai, für diese Aufgabe brauchen wir heute einen Patch!“
    Dies bedeutet, dass die Korrespondenz im Kontext einiger geführt werden kann Dokument.
  • „Kolya, gehst du heute Abend zu Dota?“
    Das heißt, sogar ein Gesprächspartnerpaar kann gleichzeitig kommunizieren zu verschiedenen Themen.
  • „Peter, Nikolay, schauen Sie im Anhang nach der Preisliste für den neuen Server.“
    Es kann also eine Nachricht geben mehrere Empfänger. In diesem Fall kann die Nachricht enthalten Angehängte Dokumente.
  • „Semyon, schau auch mal.“
    Und es sollte die Möglichkeit gegeben sein, in bestehende Korrespondenzen einzusteigen ein neues Mitglied einladen.

Bleiben wir zunächst bei dieser Liste „offensichtlicher“ Bedürfnisse.

Ohne die angewandten Besonderheiten des Problems und die damit verbundenen Einschränkungen zu verstehen, entwerfen Wirksam Es ist fast unmöglich, das Datenbankschema zu lösen.

Schritt 2: Minimale Logikschaltung

Bisher funktioniert alles sehr ähnlich wie bei der E-Mail-Korrespondenz – einem traditionellen Business-Tool. Ja, „algorithmisch“ sind viele Geschäftsprobleme einander ähnlich, daher werden die Werkzeuge zu ihrer Lösung strukturell ähnlich sein.

Lassen Sie uns das bereits erhaltene logische Diagramm der Entitätsbeziehungen korrigieren. Um unser Modell leichter verständlich zu machen, verwenden wir die primitivste Anzeigeoption ER-Modelle ohne die Komplikationen von UML- oder IDEF-Notationen:

Messenger-Datenbank (Teil 1): Entwerfen des Basis-Frameworks

In unserem Beispiel sind die Person, das Dokument und der binäre „Körper“ der Datei „externe“ Entitäten, die unabhängig voneinander ohne unseren Service existieren. Daher werden wir sie in Zukunft einfach als einige Links „irgendwo“ mit UUID wahrnehmen.

Ziehen Diagramme so einfach wie möglich - Die meisten Leute, denen Sie sie zeigen werden, sind keine Experten im Lesen von UML/IDEF. Aber unbedingt zeichnen.

Schritt 3: Skizzieren der Tabellenstruktur

Über Tabellen- und FeldnamenDie „russischen“ Namen von Feldern und Tabellen können unterschiedlich behandelt werden, aber das ist Geschmackssache. Weil das hier bei Tensor Es gibt keine ausländischen Entwickler, und PostgreSQL ermöglicht es uns, Namen sogar in Hieroglyphen anzugeben, wenn dies der Fall ist in Anführungszeichen eingeschlossen, dann bevorzugen wir es, Objekte eindeutig und klar zu benennen, damit es keine Unstimmigkeiten gibt.
Da uns viele Menschen gleichzeitig Nachrichten schreiben, kann es sein, dass einige von ihnen dies sogar tun offline, dann ist die einfachste Option Verwenden Sie UUIDs als Bezeichner nicht nur für externe Entitäten, sondern auch für alle Objekte innerhalb unseres Dienstes. Darüber hinaus können sie sogar auf der Clientseite generiert werden. Dies hilft uns, das Senden von Nachrichten zu unterstützen, wenn die Datenbank vorübergehend nicht verfügbar ist und die Wahrscheinlichkeit einer Kollision äußerst gering ist.

Die Entwurfstabellenstruktur in unserer Datenbank sieht folgendermaßen aus:
Tische: RU

CREATE TABLE "Тема"(
  "Тема"
    uuid
      PRIMARY KEY
, "Документ"
    uuid
, "Название"
    text
);

CREATE TABLE "Сообщение"(
  "Сообщение"
    uuid
      PRIMARY KEY
, "Тема"
    uuid
, "Автор"
    uuid
, "ДатаВремя"
    timestamp
, "Текст"
    text
);

CREATE TABLE "Адресат"(
  "Сообщение"
    uuid
, "Персона"
    uuid
, PRIMARY KEY("Сообщение", "Персона")
);

CREATE TABLE "Файл"(
  "Файл"
    uuid
      PRIMARY KEY
, "Сообщение"
    uuid
, "BLOB"
    uuid
, "Имя"
    text
);

Tabellen: EN

CREATE TABLE theme(
  theme
    uuid
      PRIMARY KEY
, document
    uuid
, title
    text
);

CREATE TABLE message(
  message
    uuid
      PRIMARY KEY
, theme
    uuid
, author
    uuid
, dt
    timestamp
, body
    text
);

CREATE TABLE message_addressee(
  message
    uuid
, person
    uuid
, PRIMARY KEY(message, person)
);

CREATE TABLE message_file(
  file
    uuid
      PRIMARY KEY
, message
    uuid
, content
    uuid
, filename
    text
);

Bei der Beschreibung eines Formats ist es am einfachsten, mit dem „Entwickeln“ des Verbindungsdiagramms zu beginnen aus Tabellen, auf die nicht verwiesen wird sich niemandem gegenüber.

Schritt 4: Finden Sie nicht offensichtliche Bedürfnisse heraus

Das war's, wir haben eine Datenbank entworfen, in der Sie perfekt schreiben können irgendwie lesen.

Versetzen wir uns in die Lage des Nutzers unseres Dienstes – was wollen wir damit machen?

  • Aktuelle Beiträge
    Es chronologisch sortiert ein Verzeichnis „meiner“ Nachrichten basierend auf verschiedenen Kriterien. Wo ich einer der Empfänger bin, wo ich der Autor bin, wo sie mir geschrieben haben und ich nicht geantwortet habe, wo sie mir nicht geantwortet haben, ...
  • Teilnehmer der Korrespondenz
    Wer nimmt überhaupt an diesem langen, langen Chat teil?

Unsere Struktur ermöglicht es uns, diese beiden Probleme „im Allgemeinen“, jedoch nicht schnell, zu lösen. Das Problem besteht darin, dass innerhalb der ersten Aufgabe sortiert werden muss Index kann nicht erstellt werden, geeignet für jeden Teilnehmer (und Sie müssen alle Datensätze extrahieren), und um den zweiten zu lösen, den Sie benötigen Alle Nachrichten extrahieren zum Thema.

Unbeabsichtigte Benutzeraufgaben können fett dargestellt werden Kreuz auf Produktivität.

Schritt 5: Intelligente Denormalisierung

Unsere beiden Probleme werden durch zusätzliche Tabellen gelöst, in denen wir dies tun werden Duplikat eines Teils der Daten, notwendig, um auf ihnen für unsere Aufgaben geeignete Indizes zu bilden.
Messenger-Datenbank (Teil 1): Entwerfen des Basis-Frameworks

Tische: RU

CREATE TABLE "РеестрСообщений"(
  "Владелец"
    uuid
, "ТипРеестра"
    smallint
, "ДатаВремя"
    timestamp
, "Сообщение"
    uuid
, PRIMARY KEY("Владелец", "ТипРеестра", "Сообщение")
);
CREATE INDEX ON "РеестрСообщений"("Владелец", "ТипРеестра", "ДатаВремя" DESC);

CREATE TABLE "УчастникТемы"(
  "Тема"
    uuid
, "Персона"
    uuid
, PRIMARY KEY("Тема", "Персона")
);

Tabellen: EN

CREATE TABLE message_registry(
  owner
    uuid
, registry
    smallint
, dt
    timestamp
, message
    uuid
, PRIMARY KEY(owner, registry, message)
);
CREATE INDEX ON message_registry(owner, registry, dt DESC);

CREATE TABLE theme_participant(
  theme
    uuid
, person
    uuid
, PRIMARY KEY(theme, person)
);

Hier haben wir zwei typische Ansätze zur Erstellung von Hilfstabellen angewendet:

  • Datensätze multiplizieren
    Aus einem ersten Nachrichtendatensatz erstellen wir mehrere Folgedatensätze in unterschiedlichen Registertypen für unterschiedliche Eigentümer – sowohl für den Absender als auch für den Empfänger. Aber jedes der Register fällt nun auf den Index – schließlich wollen wir im typischen Fall nur die erste Seite sehen.
  • Einzigartige Rekorde
    Jedes Mal, wenn Sie eine Nachricht innerhalb eines bestimmten Themas senden, reicht es aus zu prüfen, ob ein solcher Eintrag bereits vorhanden ist. Wenn nicht, fügen Sie es unserem „Wörterbuch“ hinzu.

Im nächsten Teil des Artikels werden wir darüber sprechen Implementierung der Partitionierung in die Struktur unserer Datenbank ein.

Source: habr.com

Kommentar hinzufügen