Datenbank des Messengers (Teil 1): Entwurf des DatenbankgerĂŒsts

Wie man GeschĂ€ftsanforderungen in spezifische Datenstrukturen umwandelt am Beispiel der Planung einer Datenbank von Grund auf fĂŒr einen Messenger.

Datenbank des Messengers (Teil 1): Entwurf des DatenbankgerĂŒsts
Unsere Datenbank wird nicht so groß und verteilt sein wie die von VKontakte oder Badoo, sondern eher bescheiden, aber dennoch gut – funktional, schnell und auf einem Server Platz finden. PostgreSQL – damit wir einen separaten Instanz des Dienstes irgendwo anders bereitstellen können, zum Beispiel.

Deshalb werden wir keine Fragen zu Sharding, Replikation und geo-distribuierten Systemen behandeln, sondern uns auf die strukturellen Lösungen innerhalb der Datenbank konzentrieren.

Schritt 1: Ein wenig geschÀftsspezifische Informationen

Wir werden unseren Nachrichtenaustausch nicht abstrakt entwerfen, sondern in die Umgebung eines Unternehmensnetzwerksintegrieren. Das heißt, die Menschen kommunizieren nicht einfach, sondern interagieren im Kontext der Lösung spezifischer GeschĂ€ftsprobleme.

Welche Aufgaben hat ein Unternehmen?... Schauen wir uns das am Beispiel von Vasily, dem Leiter der Entwicklungsabteilung, an.

  • "Nikolai, der Patch fĂŒr diese Aufgabe wird bereits heute benötigt!"
    Das bedeutet, dass die Kommunikation im Kontext von etwas stattfinden kann. des Dokuments.
  • "Koya, lass uns heute Abend Dota spielen?"
    Das bedeutet, dass sogar bei einem Paar von GesprĂ€chspartnern gleichzeitig ĂŒber verschiedene Themen kommuniziert werden kann..
  • „Peter, Nikolai, schaut euch im Anhang die Preisliste fĂŒr den neuen Server an.”
    So kann eine Nachricht mehrere EmpfÀnger haben.. Dabei kann die Nachricht angehÀngte Dateien enthalten..
  • „Semen, du solltest auch einen Blick darauf werfen.”
    Und es sollte möglich sein, einen neuen Teilnehmer in die bereits bestehende Korrespondenz einzuladen..

Lassen Sie uns vorerst bei dieser Liste der „offensichtlichen” BedĂŒrfnisse bleiben.

Ohne das VerstĂ€ndnis der spezifischen Anforderungen und der ihnen auferlegten EinschrĂ€nkungen ist es praktisch unmöglich, eine effektive Datenbankschema fĂŒr deren Lösung zu entwerfen.

Schritt 2: Minimales logisches Schema

VorlĂ€ufig Ă€hnelt alles sehr der E-Mail-Korrespondenz — einem traditionellen GeschĂ€ftsfĂŒhrungstool. Ja, „algorithmisch” Ă€hneln sich viele GeschĂ€ftsaufgaben, daher werden auch die Werkzeuge zu ihrer Lösung strukturell Ă€hnlich sein.

Lassen Sie uns das bereits erhaltene logische Schema der EntitÀtenbeziehungen festhalten. Zur Vereinfachung des VerstÀndnisses unserer Modell nutzen wir die einfachste Form der Darstellung ER-Modelle ohne komplizierte UML- oder IDEF-Notation.

Datenbank des Messengers (Teil 1): Entwurf des DatenbankgerĂŒsts

In unserem Beispiel sind die Persona, das Dokument und das binĂ€re „Körper“ der Datei „externe“ EntitĂ€ten, die unabhĂ€ngig von unserem Dienst existieren. Daher betrachten wir sie kĂŒnftig einfach als Links „irgendwo“ ĂŒber UUID.

Zeichnen Sie Schemen so einfach wie möglich — Die meisten derjenigen, die Sie sie zeigen werden, sind keine Experten im Lesen von UML/IDEF. Aber zeichnen Sie unbedingt.

Schritt 3: Skizzieren Sie die Struktur der Tabellen

Über die Namen von Tabellen und FeldernZu 'russischen' Bezeichnungen fĂŒr Felder und Tabellen kann man unterschiedlich stehen, aber das ist Geschmackssache. Da wir in 'Tensor' keine auslĂ€ndischen Entwickler haben und PostgreSQL uns erlaubt, auch mit Hieroglyphen zu benennen, wenn sie in AnfĂŒhrungszeichen stehen, bevorzugen wir es, Objekte eindeutig verstĂ€ndlich zu benennen, um MissverstĂ€ndnisse zu vermeiden.
Da viele Menschen gleichzeitig Nachrichten schreiben, können einige von ihnen dies im Offline-Modus, ist die einfachste Option — UUIDs als Identifikatoren zu verwenden nicht nur fĂŒr externe EntitĂ€ten, sondern auch fĂŒr alle Objekte innerhalb unseres Dienstes. Zudem können sie sogar auf der Client-Seite generiert werden — das hilft uns, den Versand von Nachrichten bei kurzfristiger NichtverfĂŒgbarkeit der DB aufrechtzuerhalten, und die Wahrscheinlichkeit einer Kollision ist Ă€ußerst niedrig.

Die Rohstruktur der Tabellen in unserer Datenbank wird folgendermaßen aussehen:
Tabellen : RU

ERSTELLE TABELLE "Thema"(
  "Thema"
    uuid
      PRIMARY KEY
, "Dokument"
    uuid
, "Titel"
    text
);

ERSTELLE TABELLE "Nachricht"(
  "Nachricht"
    uuid
      PRIMARY KEY
, "Thema"
    uuid
, "Autor"
    uuid
, "DatumUhrzeit"
    timestamp
, "Text"
    text
);

ERSTELLE TABELLE "EmpfÀnger"(
  "Nachricht"
    uuid
, "Person"
    uuid
, PRIMARY KEY("Nachricht", "Person")
);

ERSTELLE TABELLE "Datei"(
  "Datei"
    uuid
      PRIMARY KEY
, "Nachricht"
    uuid
, "BLOB"
    uuid
, "Name"
    text
);

Tabellen : EN

ERSTELLE TABELLE thema(
  thema
    uuid
      PRIMARY KEY
, dokument
    uuid
, titel
    text
);

ERSTELLE TABELLE nachricht(
  nachricht
    uuid
      PRIMARY KEY
, thema
    uuid
, autor
    uuid
, dt
    timestamp
, text
    text
);

ERSTELLE TABELLE nachricht_empfÀnger(
  nachricht
    uuid
, person
    uuid
, PRIMARY KEY(nachricht, person)
);

ERSTELLE TABELLE nachricht_datei(
  datei
    uuid
      PRIMARY KEY
, nachricht
    uuid
, inhalt
    uuid
, dateiname
    text
);

Am einfachsten beginnt man bei der Beschreibung des Formats, indem man die Beziehungsgrafik "enthĂŒllt". von Tabellen, die nicht referenzieren sich selbst auf niemanden.

Schritt 4: Offensichtliche BedĂŒrfnisse klĂ€ren

So, wir haben eine Datenbank entworfen, in die man ausgezeichnet schreiben und irgendwie lesen kann.

Lassen Sie uns in die Lage des Nutzers unseres Services versetzen — was wĂŒrden wir mit dessen Hilfe tun wollen?

  • Neueste Nachrichten
    Das chronologisch sortiert nach verschiedenen Kriterien eine Übersicht meiner Nachrichten. Wo ich einer der Adressaten bin, wo ich der Autor bin, wo man mir geschrieben hat, aber ich nicht geantwortet habe, wo mir nicht geantwortet wurde, 

  • Teilnehmer der Konversation
    Wer nimmt eigentlich an diesem langen, langen Chat teil?

Unsere Struktur ermöglicht es, beide Aufgaben ‚insgesamt‘ zu lösen, aber schnell – nein. Das Problem ist, dass fĂŒr die Sortierung im Rahmen der ersten Aufgabe es unmöglich ist, einen Index zu erstellen, der fĂŒr jeden der Teilnehmer geeignet ist (und man muss alle Aufzeichnungen abrufen), und zur Lösung der zweiten Aufgabe ist es notwendig alle Nachrichten zum Thema zu extrahieren.

Unvorhergesehene Benutzeraufgaben können ein fettes Kreuz fĂŒr die Leistung setzen..

Schritt 5: Sinnvolle Denormalisierung

Beide unsere Probleme können durch zusĂ€tzliche Tabellen gelöst werden, in die wir einen Teil der Daten duplizieren, die erforderlich sind, um geeignete Indizes fĂŒr unsere Aufgaben zu erstellen.
Datenbank des Messengers (Teil 1): Entwurf des DatenbankgerĂŒsts

Tabellen : RU

CREATE TABLE "Nachrichtenregister"(
  "EigentĂŒmer"
    uuid
, "RegistryTyp"
    smallint
, "DatumUhrzeit"
    timestamp
, "Nachricht"
    uuid
, PRIMARY KEY("EigentĂŒmer", "RegistryTyp", "Nachricht")
);
CREATE INDEX ON "Nachrichtenregister"("EigentĂŒmer", "RegistryTyp", "DatumUhrzeit" DESC);

CREATE TABLE "ThemenTeilnehmer"(
  "Thema"
    uuid
, "Person"
    uuid
, PRIMARY KEY("Thema", "Person")
);

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 angewendet, die beim Erstellen von Hilfstabellen verwendet werden:

  • Multiplikation von DatensĂ€tzen
    Wir erstellen aus einem ursprĂŒnglichen Nachrichtendatensatz mehrere FolgedatensĂ€tze in verschiedene Arten von Registern fĂŒr unterschiedliche EigentĂŒmer — sowohl fĂŒr den Absender als auch fĂŒr den EmpfĂ€nger. So wird jedes Register nun auf einen Index gelegt — denn im typischen Fall möchten wir nur die erste Seite sehen.
  • Eindeutigkeit der DatensĂ€tze
    Bei jedem Versenden einer Nachricht innerhalb eines bestimmten Themas genĂŒgt es zu ĂŒberprĂŒfen, ob ein solcher Datensatz bereits existiert. Wenn nicht — fĂŒgen wir ihn in unser „Wörterbuch“ ein.

Im nÀchsten Teil des Artikels wird es um Implementierung von Partitionierung in die Struktur unserer Datenbank.

Quelle: habr.com

Erwerben Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server đŸ”„ Kaufen Sie zuverlĂ€ssiges Hosting fĂŒr Websites mit DDoS-Schutz, VPS VDS-Server | ProHoster