Messenger-database (deel 1): het ontwerpen van het basisframework

Hoe u bedrijfsvereisten kunt vertalen naar specifieke datastructuren aan de hand van het voorbeeld van het helemaal opnieuw ontwerpen van een messenger-database.

Messenger-database (deel 1): het ontwerpen van het basisframework
Onze basis zal niet zo groot en verspreid zijn, zoals VKontakte of Badoo, maar “zo was het”, maar het was goed - functioneel, snel en passen op één server PostgreSQL - zodat u bijvoorbeeld ergens aan de zijkant een afzonderlijk exemplaar van de service kunt implementeren.

Daarom zullen we de kwesties van sharding, replicatie en geo-gedistribueerde systemen niet bespreken, maar zullen we ons concentreren op circuitoplossingen binnen de database.

Stap 1: Enkele zakelijke details

Wij gaan onze berichtgeving niet abstract vormgeven, maar integreren in de omgeving zakelijk sociaal netwerk. Dat wil zeggen dat onze mensen niet ‘slechts corresponderen’, maar met elkaar communiceren in het kader van het oplossen van bepaalde bedrijfsproblemen.

En wat zijn de taken van een bedrijf? Laten we eens kijken naar het voorbeeld van Vasily, het hoofd van de ontwikkelingsafdeling.

  • "Nikolai, voor deze taak hebben we vandaag een patch nodig!"
    Dit betekent dat correspondentie in de context van sommigen kan worden gevoerd document.
  • 'Kolya, ga je vanavond naar Dota?'
    Dat wil zeggen dat zelfs één paar gesprekspartners tegelijkertijd kan communiceren over verschillende onderwerpen.
  • “Peter, Nikolay, kijk in de bijlage voor de prijslijst voor de nieuwe server.”
    Eén boodschap kan dus hebben meerdere ontvangers. In dit geval kan het bericht het volgende bevatten Bijgevoegde bestanden.
  • ‘Semyon, kijk ook eens.’
    En er moet een mogelijkheid zijn om bestaande correspondentie aan te gaan nodig een nieuw lid uit.

Laten we voorlopig stilstaan ​​bij deze lijst met “voor de hand liggende” behoeften.

Zonder de toegepaste details van het probleem en de beperkingen die eraan worden gegeven te begrijpen, ontwerpen efficiënt databaseschema om het op te lossen is bijna onmogelijk.

Stap 2: Minimaal logisch circuit

Tot nu toe werkt alles vrijwel hetzelfde als e-mailcorrespondentie: een traditioneel zakelijk hulpmiddel. Ja, ‘algoritmisch’ lijken veel bedrijfsproblemen op elkaar, daarom zullen de tools om ze op te lossen structureel vergelijkbaar zijn.

Laten we het reeds verkregen logische diagram van entiteitsrelaties verbeteren. Om ons model begrijpelijker te maken, zullen we de meest primitieve weergaveoptie gebruiken ER-modellen zonder de complicaties van UML- of IDEF-notaties:

Messenger-database (deel 1): het ontwerpen van het basisframework

In ons voorbeeld zijn de persoon, het document en de binaire ‘body’ van het bestand ‘externe’ entiteiten die onafhankelijk bestaan ​​zonder onze service. Daarom zullen we ze in de toekomst eenvoudigweg waarnemen als enkele links “ergens” door UUID.

Tekenen diagrammen zo eenvoudig mogelijk - de meeste mensen aan wie u ze laat zien, zijn geen experts in het lezen van UML/IDEF. Maar zorg ervoor dat je tekent.

Stap 3: Schets van de tabelstructuur

Over tabel- en veldnamenDe “Russische” namen van velden en tabellen kunnen anders worden behandeld, maar dit is een kwestie van smaak. Omdat de hier bij Tensor er zijn geen buitenlandse ontwikkelaars, en PostgreSQL stelt ons in staat namen te geven, zelfs in hiërogliefen, als ze dat wel zijn tussen aanhalingstekens, dan geven we er de voorkeur aan om objecten ondubbelzinnig en duidelijk te benoemen, zodat er geen discrepanties ontstaan.
Omdat veel mensen tegelijk berichten naar ons schrijven, doen sommigen dit misschien zelfs offline, dan is de eenvoudigste optie gebruik UUID's als identificatiegegevens niet alleen voor externe entiteiten, maar ook voor alle objecten binnen onze dienst. Bovendien kunnen ze zelfs aan de clientzijde worden gegenereerd - dit zal ons helpen bij het ondersteunen van het verzenden van berichten wanneer de database tijdelijk niet beschikbaar is en de kans op een botsing extreem laag is.

De concepttabelstructuur in onze database ziet er als volgt uit:
Tafels: 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: NL

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
);

Het eenvoudigste bij het beschrijven van een formaat is het beginnen met het “afwikkelen” van de verbindingsgrafiek uit tabellen waarnaar niet wordt verwezen zichzelf voor niemand.

Stap 4: Ontdek niet voor de hand liggende behoeften

Dat is alles, we hebben een database ontworpen waarin u perfect kunt schrijven en ergens om te lezen.

Laten we onszelf in de schoenen plaatsen van de gebruiker van onze dienst: wat willen we ermee doen?

  • Laatste berichten
    Het chronologisch gesorteerd een register van “mijn” berichten op basis van verschillende criteria. Waar ik een van de ontvangers ben, waar ik de auteur ben, waar ze mij schreven en ik niet antwoordde, waar ze mij niet antwoordden, ...
  • Deelnemers aan de correspondentie
    Wie neemt er überhaupt deel aan dit lange, lange gesprek?

Onze structuur stelt ons in staat deze beide problemen ‘in het algemeen’ op te lossen, maar niet snel. Het probleem is dat voor het sorteren binnen de eerste taak kan geen index maken, geschikt voor elk van de deelnemers (en je zult alle records moeten extraheren), en om de tweede op te lossen die je nodig hebt pak alle berichten uit over dit onderwerp.

Onbedoelde gebruikerstaken kunnen vetgedrukt worden weergegeven kruis op productiviteit.

Stap 5: Slimme denormalisatie

Onze beide problemen zullen worden opgelost door extra tabellen waarin we dat zullen doen dupliceer een deel van de gegevens, noodzakelijk om daarop indices te vormen die geschikt zijn voor onze taken.
Messenger-database (deel 1): het ontwerpen van het basisframework

Tafels: RU

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

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

Tabellen: NL

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 hebben we twee typische benaderingen toegepast die worden gebruikt bij het maken van hulptabellen:

  • Records vermenigvuldigen
    Met behulp van één initieel berichtrecord creëren we meerdere vervolgrecords in verschillende soorten registers voor verschillende eigenaren - zowel voor de afzender als voor de ontvanger. Maar elk van de registers valt nu op de index - in een typisch geval willen we immers alleen de eerste pagina zien.
  • Unieke records
    Elke keer dat u een bericht verzendt binnen een specifiek onderwerp, volstaat het om te controleren of een dergelijk bericht al bestaat. Zo niet, voeg het dan toe aan ons “woordenboek”.

In het volgende deel van het artikel zullen we het hebben over implementatie van partitie in de structuur van onze database.

Bron: www.habr.com

Voeg een reactie