Messenger-database (del 1): design rammen pÄ databasen

Hvordan man kan oversĂŠtte forretningskrav til konkrete datastrukturer ved at designe en database til en messenger "fra bunden".

Messenger-database (del 1): design rammen pÄ databasen
Vores database vil ikke vĂŠre sĂ„ omfattende og distribueret, som hos VKontakte eller Badoo, men "bare for at have det", skal den vĂŠre god — funktionel, hurtig og kunne vĂŠre pĂ„ Ă©n server PostgreSQL — sĂ„ vi kan implementere en separat tjenesteinstans et sted, for eksempel.

Derfor vil vi ikke berÞre spÞrgsmÄl om sharding, replikering og geografisk distribuerede systemer, men fokusere pÄ skematiske lÞsninger inden for databasen.

Trin 1: Lidt forretningsspecifik viden

Vi vil designe vores beskedudveksling ikke abstrakt, men indbygget i miljĂžet af et virksomhedssocialt netvĂŠrk. Det vil sige, at folk ikke "bare skriver til hinanden", men kommunikerer i konteksten af at lĂžse bestemte forretningsopgaver.

Hvilke opgaver har virksomhederne? Lad os se pÄ et eksempel med Vasily - lederen af udviklingsafdelingen.

  • "Nikolaj, vi har brug for en patch til denne opgave i dag!"
    Det betyder, at kommunikationen kan finde sted i konteksten af et dokument.
  • "Kola, skal vi spille Dota i aften?"
    Det vil sige, at selv for et par samtalepartnere kan kommunikationen finde sted om forskellige emner.
  • "Petr, Nikolaj, kig i det vedhĂŠftede dokument for prisen pĂ„ den nye server."
    SĂ„ et enkelt besked kan have flere modtagere.Desuden kan en besked indeholde vedhĂŠftede filer.
  • "Semen, du skal ogsĂ„ tage et kig."
    Og der skal vÊre mulighed for at invitere en ny deltager ind i en eksisterende samtale Lad os holde os til denne liste af "Äbenlyse" behov..

Uden forstÄelse af de applikationsspecifikke opgaver og deres begrÊnsninger er det praktisk talt umuligt at designe

en effektiv database schema til at lĂžse dem. Trin 2: Minimal logisk skema

Skematisk set ligner alt stadig meget en email-korrespondance — et traditionelt vĂŠrktĂžj til at drive forretning. SĂ„ ja, "algoritmisk" minder mange forretningsopgaver om hinanden, derfor vil vĂŠrktĂžjerne til at lĂžse dem ogsĂ„ have strukturel lighed.

Lad os fastholde den logiske skema for enhedsrelationerne, vi allerede har fÄet. For at forenkle forstÄelsen af vores model vil vi bruge den mest primitive form for visning

af ER-modellen. ER-modeller uden komplicerede UML eller IDEF-notationer:

Messenger-database (del 1): design rammen pÄ databasen

I vores eksempel er person, dokument og den binĂŠre "krop" af filen "eksterne" enheder, der eksisterer uafhĂŠngigt af vores service. Derfor vil vi blot opfatte dem som nogle links "et eller andet sted" via UUID.

Tegn skemaer sĂ„ enkelt som muligt — de fleste af dem, du viser dem til, er ikke eksperter i at lĂŠse UML/IDEF. Men — sĂžrg for at tegne.

Trin 3: Skitser strukturen af tabeller

Om navne pÄ tabeller og felterMan kan have forskellige holdninger til "russiske" navne pÄ felter og tabeller, men det er en smagssag. Da vi i "Tensor" ikke har udenlandske udviklere, og PostgreSQL tillader os at give navne selv i hieroglyffer, sÄ lÊnge de er indkapslet i anfÞrselstegn, sÄ foretrÊkker vi at navngive objekter klart og tydeligt for at undgÄ misforstÄelser.
Da mange mennesker skriver beskeder til os pĂ„ Ă©n gang, kan nogle endda gĂžre det i offline-tilstand, sĂ„ den enkleste lĂžsning er at bruge UUID som identifikatorer ikke kun for eksterne enheder, men ogsĂ„ for alle objekter inden for vores service. Desuden kan de genereres selv pĂ„ klientsiden — det hjĂŠlper os med at stĂžtte afsendelse af beskeder ved kortvarig utilgĂŠngelighed af databasen, og risikoen for kollision er ekstremt lille.

Den udkastede struktur af tabellerne i vores database vil have fĂžlgende udseende:
Tabeller : RU

CREATE TABLE "Emne"(
  "Emne"
    uuid
      PRIMARY KEY
, "Dokument"
    uuid
, "Titel"
    text
);

CREATE TABLE "Besked"(
  "Besked"
    uuid
      PRIMARY KEY
, "Emne"
    uuid
, "Forfatter"
    uuid
, "DatoTid"
    timestamp
, "Tekst"
    text
);

CREATE TABLE "Modtager"(
  "Besked"
    uuid
, "Person"
    uuid
, PRIMARY KEY("Besked", "Person")
);

CREATE TABLE "Fil"(
  "Fil"
    uuid
      PRIMARY KEY
, "Besked"
    uuid
, "BLOB"
    uuid
, "Navn"
    text
);

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

Det simpleste, nÄr man beskriver formatet, er at begynde at "folde" forbindelsesgrafen fra tabeller, der ikke henviser til nogen.

Trin 4: Afklare skjulte behov

Det er det, vi har designet en database, hvor man kan skrive og pÄ en eller anden mÄde lÊse.

Lad os sétte os i brugerens sted — hvad vi þnsker at gþre med vores service?

  • Seneste beskeder
    Dette kronologisk sorteret register over 'mine' beskeder. Hvor jeg er en af modtagerne, hvor jeg er forfatter, hvor jeg er blevet skrevet til, men ikke svarede, hvor jeg ikke fik svar, 

  • Deltagere i samtalen
    Hvem deltager egentlig i denne lange chat?

Vores struktur gĂžr det muligt at lĂžse begge disse opgaver, men hurtigt — nej. Problemet er, at det er umuligt at oprette et indeks , der passer til hver deltager (og vi mĂ„ hente alle registreringer), mens det for at lĂžse den anden opgave er nĂždvendigtat hente alle beskeder om emnet. Uforudsete brugeropgaver kan sĂŠtte en fed

streg over ydeevnen Trin 5: Fornuftig denormalisering.

Begge vores problemer kan lĂžses med ekstra tabeller, hvor vi vil

duplikere en del af de data , der er nĂždvendige for at danne passende indekser til vores opgaver.CREATE TABLE "MessageRegistry"( "Owner" uuid , "RegistryType" smallint , "Datetime" timestamp , "Message" uuid , PRIMARY KEY("Owner", "RegistryType", "Message") ); CREATE INDEX ON "MessageRegistry"("Owner", "RegistryType", "Datetime" DESC);CREATE TABLE "ThemeParticipant"( "Theme" uuid , "Person" uuid , PRIMARY KEY("Theme", "Person") );
Messenger-database (del 1): design rammen pÄ databasen

Tabeller : RU

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

Tabeller : EN

Her har vi anvendt to typiske metoder, der bruges ved oprettelse af hjĂŠlpe-tabeller:

Multiplicering af optegnelser

  • Vi danner for hver enkelt indledende besked straks flere fĂžlgeoptegnelser i forskellige typer registrer for forskellige ejere — bĂ„de for afsenderen og modtageren. Men nu passer hver registrering ind pĂ„ indekset — for i typisk tilfĂŠlde Ăžnsker vi kun at se fĂžrste side.
    Unikalisering af optegnelser
  • Ved hver afsendelse af en besked inden for et bestemt emne er det nok at kontrollere, om en sĂ„dan optegnelse allerede findes. Hvis ikke — tilfĂžjer vi den til vores 'ordbog'.
    I den nÊste del af artiklen vil der vÊre fokus pÄ

implementering af partitionering i strukturen af vores database. Arkitektur til opbevaring og levering af billeder i Badoo

Kilde: habr.com

KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KĂžb pĂ„lidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster