Messenger-database (del 1): utforming av basisrammeverket

Hvordan du kan oversette forretningskrav til spesifikke datastrukturer ved å bruke eksemplet med å designe en messenger-database fra bunnen av.

Messenger-database (del 1): utforming av basisrammeverket
Vår base vil ikke være like stor og distribuert, som VKontakte eller Badoo, men "slik at det var", men det var bra - funksjonelt, raskt og passer på én server PostgreSQL – slik at du kan distribuere en egen forekomst av tjenesten et sted på siden, for eksempel.

Derfor vil vi ikke berøre spørsmålene om sharding, replikering og geo-distribuerte systemer, men vil fokusere på kretsløsninger inne i databasen.

Trinn 1: Noen forretningsdetaljer

Vi vil ikke designe budskapet vårt abstrakt, men integrere det i miljøet bedriftens sosiale nettverk. Det vil si at våre folk ikke «bare korresponderer», men kommuniserer med hverandre i sammenheng med å løse visse forretningsproblemer.

Og hva er oppgavene til en virksomhet?.. La oss se på eksemplet til Vasily, lederen for utviklingsavdelingen.

  • "Nikolai, for denne oppgaven trenger vi en lapp i dag!"
    Dette betyr at korrespondanse kan føres i sammenheng med enkelte dokument.
  • "Kolya, skal du til Dota i kveld?"
    Det vil si at til og med ett par samtalepartnere kan kommunisere samtidig om ulike emner.
  • "Peter, Nikolay, se i vedlegget for prislisten for den nye serveren."
    Så én melding kan ha flere mottakere. I dette tilfellet kan meldingen inneholde Vedlagte filer.
  • "Semyon, ta en titt også."
    Og det bør være anledning til å inngå eksisterende korrespondanse invitere et nytt medlem.

La oss dvele ved denne listen over "åpenbare" behov for nå.

Uten å forstå de anvendte spesifikasjonene til problemet og begrensningene gitt til det, design effektive databaseskjema for å løse det er nesten umulig.

Trinn 2: Minimal Logic Circuit

Så langt fungerer alt veldig likt e-postkorrespondanse - et tradisjonelt forretningsverktøy. Ja, "algoritmisk" ligner mange forretningsproblemer på hverandre, derfor vil verktøyene for å løse dem være strukturelt like.

La oss fikse det allerede oppnådde logiske diagrammet over enhetsforhold. For å gjøre modellen vår lettere å forstå, vil vi bruke det mest primitive visningsalternativet ER-modeller uten komplikasjoner av UML- eller IDEF-notasjoner:

Messenger-database (del 1): utforming av basisrammeverket

I vårt eksempel er personen, dokumentet og den binære "kroppen" til filen "eksterne" enheter som eksisterer uavhengig uten vår tjeneste. Derfor vil vi ganske enkelt oppfatte dem i fremtiden som noen lenker "et sted" av UUID.

Tegne diagrammer så enkle som mulig - de fleste du vil vise dem til er ikke eksperter på å lese UML/IDEF. Men sørg for å tegne.

Trinn 3: Skissere tabellstrukturen

Om tabell- og feltnavnDe "russiske" navnene på felt og tabeller kan behandles annerledes, men dette er en smakssak. Fordi det her på Tensor det er ingen utenlandske utviklere, og PostgreSQL lar oss gi navn selv i hieroglyfer, hvis de vedlagt anførselstegn, da foretrekker vi å navngi objekter entydig og tydelig slik at det ikke er noen avvik.
Siden mange mennesker skriver meldinger til oss på en gang, kan noen av dem til og med gjøre dette offline, da er det enkleste alternativet bruke UUID-er som identifikatorer ikke bare for eksterne enheter, men også for alle objekter i tjenesten vår. Dessuten kan de genereres selv på klientsiden - dette vil hjelpe oss å støtte sending av meldinger når databasen er midlertidig utilgjengelig, og sannsynligheten for en kollisjon er ekstremt lav.

Tabellutkastet i databasen vår vil se slik ut:
Tabeller: 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
);

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 når du skal beskrive et format er å begynne å "vikle av" koblingsgrafen fra tabeller som ikke er referert seg til ingen.

Trinn 4: Finn ut ikke-åpenbare behov

Det er det, vi har designet en database der du kan skrive perfekt og liksom lese.

La oss sette oss inn i skoene til brukeren av tjenesten vår – hva vil vi med den?

  • Siste meldinger
    Den kronologisk sortert et register over "mine" meldinger basert på ulike kriterier. Hvor jeg er en av mottakerne, hvor jeg er forfatteren, hvor de skrev til meg og jeg ikke svarte, hvor de ikke svarte meg, ...
  • Deltakere i korrespondansen
    Hvem deltar i det hele tatt i denne lange, lange chatten?

Strukturen vår lar oss løse begge disse problemene "generelt", men ikke raskt. Problemet er at for sortering innenfor den første oppgaven kan ikke opprette indeks, egnet for hver av deltakerne (og du må trekke ut alle postene), og for å løse den andre du trenger trekke ut alle meldinger om dette emnet.

Utilsiktede brukeroppgaver kan være fet kryss på produktivitet.

Trinn 5: Smart denormalisering

Begge våre problemer vil bli løst ved hjelp av tilleggstabeller der vi vil duplisere en del av dataene, nødvendig for å danne på dem indekser som er egnet for våre oppgaver.
Messenger-database (del 1): utforming av basisrammeverket

Tabeller: RU

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

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

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 når du oppretter hjelpetabeller:

  • Multiplisere poster
    Ved hjelp av én innledende meldingspost oppretter vi flere oppfølgingsposter i ulike typer registre for ulike eiere – både for avsender og for mottaker. Men hvert av registrene faller nå på indeksen - i et typisk tilfelle vil vi tross alt bare se den første siden.
  • Unike rekorder
    Hver gang du sender en melding innenfor et spesifikt emne, er det nok å sjekke om en slik oppføring allerede eksisterer. Hvis ikke, legg den til i vår "ordbok".

I neste del av artikkelen skal vi snakke om implementering av partisjonering inn i strukturen til databasen vår.

Kilde: www.habr.com

Legg til en kommentar