DB av meldingsmessengeren (del 1): design av databasen

Hvordan kan man oversette forretningskrav til konkrete datastukturer ved Ă„ designe en database for en meldingsapp fra bunnen av.

DB av meldingsmessengeren (del 1): design av databasen
VĂ„r database vil ikke vĂŠre sĂ„ stor og distribuert, som hos VKontakte eller Badoo, men «bare for Ă„ ha noe», men det skal vĂŠre bra – funksjonelt, raskt og fĂ„ plass pĂ„ Ă©n server PostgreSQL – slik at man kan sette opp en egen tjeneste et annet sted, for eksempel.

Derfor skal vi ikke ta opp spÞrsmÄl om sharding, replikering og geo-distribuerte systemer, men fokusere pÄ skjematiske lÞsninger inne i databasen.

Trinn 1: Litt forretningsspesifikke detaljer

Vi vil designe meldingsutvekslingen ikke abstrakt, men integrere den i konteksten av et bedrifts sosialt nettverk. Det vil si at folk ikke «bare skriver til hverandre», men kommuniserer i sammenheng med Ä lÞse spesifikke forretningsoppgaver.

Og hvilke oppgaver har virksomheter?... La oss se pĂ„ et eksempel med Vasily – lederen for utviklingsavdelingen.

  • «Nikolai, vi trenger en patch for denne oppgaven i dag!»
    Dermed kan samtalen foregÄ i konteksten av en eller annen dokumentet.
  • «Kola, la oss spille Dota i kveld?»
    SĂ„ selv med ett par samtalepartnere kan kommunikasjonen skje om flere temaer.
  • «Petr, Nikolai, se vedlegget for prisen pĂ„ den nye serveren.»
    Dermed kan en melding ha flere mottakere. I tillegg kan meldingen inneholde vedlagte filer.
  • «Semen, og du ogsĂ„, ta en titt.»
    Og det mÄ vÊre mulig Ä invitere en ny deltaker til en allerede eksisterende samtale Vi stopper forelÞpig med denne listen over «Äpenbare» behov..

Uten Ä forstÄ den praktiske spesifikasjonen av oppgaven og de begrensningene den setter, er det nesten umulig Ä designe

en effektiv databasestruktur for Ă„ lĂžse den. Trinn 2: Minimal logisk plan

SĂ„ langt ser den skjematiske fremstillingen veldig lik e-postkorrespondanse ut – et tradisjonelt verktĂžy for forretning. Ja, «algoritmisk» er mange forretningsoppgaver like, sĂ„ verktĂžyene for Ă„ lĂžse dem vil vĂŠre strukturelt like.

La oss fastholde den logiske planen for entitetenes forhold vi allerede har fÄtt. For enkelhets skyld i vÄr modell vil vi bruke den enkleste varianten av representasjonen

ER-modellen uten Ă„ komplisere med UML eller IDEF-notasjoner: uten kompliserte UML- eller IDEF-notasjoner:

DB av meldingsmessengeren (del 1): design av databasen

I vÄrt eksempel er persona, dokumentet og det binÊre «kropp» av filen «eksterne» enheter som eksisterer uavhengig av vÄr tjeneste. SÄ vi vil bare oppfatte dem videre som noen lenker «et sted» via UUID.

Tegn diagrammer sĂ„ enkelt som mulig — de fleste som du vil vise dem til, er ikke eksperter pĂ„ Ă„ lese UML/IDEF. Men — husk Ă„ tegne.

Trinn 3: Utkast til tabellstrukturen

Om navnene pÄ tabeller og feltMan kan se pÄ «russiske» navne pÄ felt og tabeller pÄ forskjellige mÄter, men det er en smaksak. Siden vi i «Tensor» ikke har utenlandske utviklere, og PostgreSQL lar oss gi navn selv i hieroglyfer, hvis de er innesluttet i anfÞrselstegn, sÄ foretrekker vi Ä navngi objekter klart og entydig for Ä unngÄ misforstÄelser.
Siden mange personer skriver meldinger samtidig, kan noen av dem faktisk gjĂžre dette i offline-modus, sĂ„ det enkleste alternativet er Ă„ bruke UUID som identifikatorer ikke bare for eksterne enheter, men ogsĂ„ for alle objekter innen vĂ„r tjeneste. Og de kan genereres til og med pĂ„ klientsiden — dette vil hjelpe oss Ă„ stĂžtte sending av meldinger ved kortvarig databaseutilgjengelighet, og sjansen for kollisjon er ekstremt lav.

Den forelÞpige tabellstrukturen i databasen vÄr vil se slik ut:
Tabeller : RU

CREATE TABLE "Tema"(
  "Tema"
    uuid
      PRIMARY KEY
, "Dokument"
    uuid
, "Navn"
    text
);

CREATE TABLE "Melding"(
  "Melding"
    uuid
      PRIMARY KEY
, "Tema"
    uuid
, "Forfatter"
    uuid
, "DatoTid"
    timestamp
, "Tekst"
    text
);

CREATE TABLE "Mottaker"(
  "Melding"
    uuid
, "Persona"
    uuid
, PRIMARY KEY("Melding", "Persona")
);

CREATE TABLE "Fil"(
  "Fil"
    uuid
      PRIMARY KEY
, "Melding"
    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 enkleste ved beskrivelsen av formatet er Ä begynne Ä «puste liv» i forbindelser fra tabeller som ikke refererer til noen andre.

Trinn 4: Avdekke ikke-Äpenbare behov

Vi har designet en database hvor det er lett Ä skrive og pÄ en eller annen mÄte lese.

La oss sette oss i brukeren sin plass — hva vil vi Ăžnsker Ă„ gjĂžre med hjelp av tjenesten?

  • Siste meldinger
    Dette chronologisk sortert etter ulike kriterier en liste over «mine» meldinger. Der jeg er en av mottakerne, der jeg er forfatter, der jeg har fĂ„tt en melding, men ikke svart, hvor jeg ikke har fĂ„tt svar, 

  • Deltakere i samtalen
    Hvem deltar i denne lange, lange chatten?

VĂ„r struktur lar oss lĂžse begge disse oppgavene «generelt», men raskt – nei. Problemet er at for sortering i forbindelse med den fĂžrste oppgaven er det umulig Ă„ lage en indeks, som er passende for hver deltaker (og vi mĂ„ hente ut alle oppfĂžringer), mens for Ă„ lĂžse den andre mĂ„ vi hente ut alle meldinger om emnet.

Uforutsigbare brukeroppgaver kan sette en stor brems pÄ ytelsen.

Steg 5: Fornuftig denormalisering

Begge vÄre problemer kan lÞses med ekstra tabeller, hvor vi skal duplisere deler av dataene, som er nÞdvendige for Ä lage passende indekser for vÄre oppgaver.
DB av meldingsmessengeren (del 1): design av databasen

Tabeller : RU

CREATE TABLE "Meldingsregister"(
  "Eier"
    uuid
, "Registertype"
    smallint
, "DatoTid"
    timestamp
, "Melding"
    uuid
, PRIMARY KEY("Eier", "Registertype", "Melding")
);
CREATE INDEX ON "Meldingsregister"("Eier", "Registertype", "DatoTid" DESC);

CREATE TABLE "TemaDeltaker"(
  "Tema"
    uuid
, "Person"
    uuid
, PRIMARY KEY("Tema", "Person")
);

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

Her har vi brukt to typiske tilnĂŠrminger, som brukes ved opprettelse av hjelpe-tabeller:

  • Multiplikasjon av poster
    Vi lager flere konsekvensoppfĂžringer av en enkelt originalmelding i forskjellige registertyper for forskjellige eiere – bĂ„de for avsender og mottaker. NĂ„ ligger imidlertid hver av registrene pĂ„ indeks – for i typiske tilfeller Ăžnsker vi vanligvis kun Ă„ se den fĂžrste siden.
  • Unikalisering av oppfĂžringer
    Ved hver sending av melding innad i et bestemt tema er det tilstrekkelig Ă„ sjekke om en slik oppfĂžring allerede eksisterer. Hvis ikke – legger vi den til vĂ„r «ordbok».

I neste del av artikkelen vil vi snakke om implementering av partisjonering inn i strukturen i databasen vÄr.

Kilde: habr.com

KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster