Messenger database (part 1): designing the database framework

Hoe kunnen zakelijke vereisten worden omgezet in specifieke datastructuren aan de hand van het ontwerpen van een database voor een messenger ‘from scratch’?

Messenger database (part 1): designing the database framework
Onze database zal niet zo grootschalig en gedistribueerd zijn, zoals die van VKontakte of Badoo, maar ‘zodat het er is’, zoals het goed is — functioneel, snel en past op één server PostgreSQL — zodat we een aparte instantie van de service ergens aan de zijkant kunnen uitrollen, bijvoorbeeld.

Daarom zullen we geen vragen over sharding, replicatie en geografisch gedistribueerde systemen behandelen, maar ons concentreren op schematische oplossingen binnen de database.

Stap 1: Een beetje zakelijke specificiteit

Onze berichtwisseling gaan we niet abstract ontwerpen, maar integreren in de omgeving van een corporate social network. Dat wil zeggen, mensen ‘ruilen gewoon berichten uit’, maar communiceren met elkaar in de context van het oplossen van specifieke zakelijke taken.

Wat voor taken heeft een bedrijf?.. Laten we kijken naar het voorbeeld van Vasily — de leidinggevende van de ontwikkelingsafdeling.

  • ‘Nikolay, voor deze taak is de patch al vandaag nodig!’
    Dat betekent dat de correspondentie kan plaatsvinden in de context van een Inkomstenstructuur van een PhD-student en Post-Doc aan de EPFL.
  • ‘Kolya, laten we vanavond Dota spelen?’
    Dat wil zeggen, zelfs bij één paar gesprekspartners kan de communicatie gelijktijdig plaatsvinden over verschillende onderwerpen.
  • ‘Peter, Nikolay, kijk naar de bijlage voor de prijs van de nieuwe server.’
    Dus een bericht kan meerdere ontvangers hebben. Daarbij kan een bericht bijlagen bevatten.
  • ‘Semen, jij ook even kijken.’
    En er moet de mogelijkheid zijn om in een bestaande correspondentie een nieuwe deelnemer uit te nodigen.

Laten we voor nu bij deze lijst van ‘voor de hand liggende’ behoeften blijven.

Zonder begrip van de toegepaste specificiteit van de taak en de gestelde beperkingen is het praktisch onmogelijk om een effectieve databasestructuur voor de oplossing ervan te ontwerpen.

Stap 2: Minimale logische schema

Het schema lijkt voorlopig zeer op e-mailcommunicatie — een traditioneel hulpmiddel voor zakelijk beheer. Inderdaad, ‘algoritmisch’ zijn veel zakelijke taken vergelijkbaar, waardoor ook de hulpmiddelen voor hun oplossingen structureel overeenkomen.

Laten we het al verkregen logische schema van de relaties tussen entiteiten vastleggen. Voor de eenvoud van ons model zullen we de meest primitieve weergave gebruiken van ER-modellen zonder complicaties van UML of IDEF-notaties:

Messenger database (part 1): designing the database framework

In ons voorbeeld zijn de entiteiten persoon, document en binaire "lichaam" van het bestand "externe" eenheden die zelfstandig bestaan en onafhankelijk van onze service. Daarom nemen we ze in de vervolg gewoon waar als verwijzingen "ergens" via UUID.

Teken schema's zo eenvoudig mogelijk — de meeste mensen aan wie je ze laat zien zijn geen experts in het lezen van UML/IDEF. Maar — teken zeker.

Stap 3: We schetsen de structuur van de tabellen

Over de namen van tabellen en veldenMen kan op verschillende manieren naar "Russische" namen van velden en tabellen kijken, maar dat is een kwestie van smaak. Aangezien we in "Tensor" geen buitenlandse ontwikkelaars hebben, en PostgreSQL ons toestaat om namen zelfs in hiërogliefen te geven, als ze tussen aanhalingstekensstaan, geven we de voorkeur aan eenduidige namen voor objecten zodat er geen misverstanden ontstaan.
Aangezien berichten door veel mensen tegelijkertijd worden geschreven, kunnen sommige dit zelfs in offline-modus, is de eenvoudigste optie om UUID te gebruiken als identificatoren niet alleen voor externe entiteiten, maar ook voor alle objecten binnen onze service. Bovendien kunnen ze zelfs aan de clientzijde worden gegenereerd — dit helpt ons om de verzending van berichten te ondersteunen bij korte onbeschikbaarheid van de database, en de kans op een botsing is uiterst klein.

De ruwe structuur van de tabellen in onze database zal er als volgt uitzien:
Tabellen : RU

CREATE TABLE "Thema"(
  "Thema"
    uuid
      PRIMARY KEY
, "Document"
    uuid
, "Titel"
    text
);

CREATE TABLE "Bericht"(
  "Bericht"
    uuid
      PRIMARY KEY
, "Thema"
    uuid
, "Auteur"
    uuid
, "DatumTijd"
    timestamp
, "Tekst"
    text
);

CREATE TABLE "Adressee"(
  "Bericht"
    uuid
, "Persoon"
    uuid
, PRIMARY KEY("Bericht", "Persoon")
);

CREATE TABLE "Bestand"(
  "Bestand"
    uuid
      PRIMARY KEY
, "Bericht"
    uuid
, "BLOB"
    uuid
, "Naam"
    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
);

Het gemakkelijkste bij het beschrijven van het formaat is te beginnen met "ontknopen" het netwerk van relaties van tabellen die niet naar iets anders verwijzen. Stap 4: We ontdekken niet-overduidelijke behoeften

Dat is alles, we hebben een database ontworpen die uitstekend is voor schrijven en

op een bepaalde manier lezen. lezen.

Laten we ons inleven in de gebruiker van onze dienst — wat willen we daarmee doen?

  • Laatste berichten
    Dit is chronologisch gesorteerd een register van "mijn" berichten op verschillende criteria. Waar ik een van de ontvangers ben, waar ik de auteur ben, waar iemand mij heeft geschreven en ik niet heb geantwoord, waar ik niet ben geantwoord, …
  • Deelnemers aan de correspondentie
    Wie doet er eigenlijk mee aan deze lange chat?

Onze structuur kan beide taken "in het algemeen" oplossen, maar snel — nee. Het probleem is dat voor het sorteren binnen de eerste taak het onmogelijk is een index te creëren, geschikt voor elke deelnemer (en we zullen alle berichten moeten extraheren), en om de tweede op te lossen, is het noodzakelijk alle berichten over het onderwerp te extraheren.

Onvoorziene gebruikersvragen kunnen een zware streep zetten door de prestaties.

Stap 5: Redelijke denormalisatie

Beide problemen worden geholpen door extra tabellen waarin we een deel van de gegevens, die nodig zijn voor het vormen van geschikte indices voor onze taken, dupliceren.
Messenger database (part 1): designing the database framework

Tabellen : RU

CREATE TABLE "BerichtenRegister"(
  "Eigenaar"
    uuid
, "TypeRegister"
    smallint
, "DatumTijd"
    timestamp
, "Bericht"
    uuid
, PRIMARY KEY("Eigenaar", "TypeRegister", "Bericht")
);
CREATE INDEX ON "BerichtenRegister"("Eigenaar", "TypeRegister", "DatumTijd" DESC);

CREATE TABLE "DeelnemerOnderwerp"(
  "Onderwerp"
    uuid
, "Persoon"
    uuid
, PRIMARY KEY("Onderwerp", "Persoon")
);

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 hebben we twee typische benaderingen toegepast die vaak gebruikt worden bij het creëren van ondersteunende tabellen:

  • Vermenigvuldiging van records
    We creëren uit één oorspronkelijke bericht direct meerdere gevolgrecords in verschillende soorten registers voor verschillende eigenaren — zowel voor de afzender als voor de ontvanger. Nu komt elke register echter op een index — want in de typische situatie willen we alleen de eerste pagina zien.
  • Unificatie van records
    Bij iedere verzending van een bericht binnen een specifiek onderwerp is het genoeg om te controleren of zo'n record al bestaat. Als dat niet het geval is, voegen we het toe aan ons "woordenboek".

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

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster