Messenger-databas (del 1): designa basramverket

Hur du kan översätta affärskrav till specifika datastrukturer med hjälp av exemplet att designa en messengerdatabas från grunden.

Messenger-databas (del 1): designa basramverket
Vår bas kommer inte att vara lika stor och distribuerad, som VKontakte eller Badoo, men "så att det var", men det var bra - funktionellt, snabbt och passar på en server PostgreSQL - så att du till exempel kan distribuera en separat instans av tjänsten någonstans vid sidan av.

Därför kommer vi inte att beröra frågorna om skärning, replikering och geodistribuerade system, utan kommer att fokusera på kretslösningar inuti databasen.

Steg 1: Vissa affärsdetaljer

Vi kommer inte att utforma våra meddelanden abstrakt, utan kommer att integrera den i miljön företags sociala nätverk. Det vill säga att våra medarbetare inte "bara korresponderar" utan kommunicerar med varandra i samband med att lösa vissa affärsproblem.

Och vilka är uppgifterna för ett företag?.. Låt oss titta på exemplet med Vasily, chefen för utvecklingsavdelningen.

  • "Nikolai, för den här uppgiften behöver vi en lapp idag!"
    Detta innebär att korrespondens kan föras inom ramen för vissa dokumentet.
  • "Kolya, ska du till Dota i kväll?"
    Det vill säga att även ett par samtalspartner kan kommunicera samtidigt om olika ämnen.
  • "Peter, Nikolay, titta i bilagan för prislistan för den nya servern."
    Så, ett meddelande kan ha flera mottagare. I det här fallet kan meddelandet innehålla Bifogade filer.
  • "Semyon, ta en titt också."
    Och det borde finnas möjlighet att gå in i befintlig korrespondens bjud in en ny medlem.

Låt oss uppehålla oss vid denna lista över "uppenbara" behov för nu.

Utan att förstå de tillämpade specifikationerna av problemet och de begränsningar som ges till det, design effektiv databasschema för att lösa det är nästan omöjligt.

Steg 2: Minimal Logic Circuit

Än så länge fungerar allt väldigt likt e-postkorrespondens – ett traditionellt affärsverktyg. Ja, "algoritmiskt" liknar många affärsproblem varandra, därför kommer verktygen för att lösa dem att vara strukturellt lika.

Låt oss fixa det redan erhållna logiska diagrammet över entitetsförhållanden. För att göra vår modell lättare att förstå kommer vi att använda det mest primitiva visningsalternativet ER-modeller utan komplikationerna av UML- eller IDEF-notationer:

Messenger-databas (del 1): designa basramverket

I vårt exempel är filens person, dokument och binära "kropp" "externa" enheter som existerar oberoende utan vår tjänst. Därför kommer vi helt enkelt att uppfatta dem i framtiden som några länkar "någonstans" av UUID.

Dra diagram så enkla som möjligt - de flesta du kommer att visa dem för är inte experter på att läsa UML/IDEF. Men se till att rita.

Steg 3: Skissa tabellstrukturen

Om tabell- och fältnamnDe "ryska" namnen på fält och tabeller kan behandlas olika, men detta är en smaksak. Eftersom den här på Tensor det finns inga utländska utvecklare, och PostgreSQL tillåter oss att ge namn även i hieroglyfer, om de omsluten av citattecken, då föredrar vi att namnge objekt entydigt och tydligt så att det inte finns några avvikelser.
Eftersom många människor skriver meddelanden till oss på en gång, kan vissa av dem till och med göra detta off-line, då är det enklaste alternativet använda UUID som identifierare inte bara för externa enheter, utan också för alla objekt inom vår tjänst. Dessutom kan de genereras även på klientsidan - detta kommer att hjälpa oss att skicka meddelanden när databasen är tillfälligt otillgänglig och sannolikheten för en kollision är extremt låg.

Tabellutkastet i vår databas kommer att se ut så här:
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 enklaste när man beskriver ett format är att börja "linda upp" anslutningsgrafen från tabeller som inte hänvisas till sig till ingen.

Steg 4: Ta reda på icke-uppenbara behov

Det var allt, vi har designat en databas där du kan skriva perfekt och på något sätt att läsa.

Låt oss sätta oss i användaren av vår tjänst – vad vill vi göra med den?

  • Sista meddelanden
    Den kronologiskt sorterade ett register över "mina" meddelanden baserat på olika kriterier. Där jag är en av mottagarna, där jag är författaren, där de skrev till mig och jag inte svarade, där de svarade mig inte, ...
  • Deltagare i korrespondensen
    Vem deltar ens i denna långa, långa chatt?

Vår struktur tillåter oss att lösa båda dessa problem "i allmänhet", men inte snabbt. Problemet är att för sortering inom den första uppgiften kan inte skapa index, lämplig för var och en av deltagarna (och du måste extrahera alla poster), och för att lösa den andra du behöver extrahera alla meddelanden om detta ämne.

Oavsiktliga användaruppgifter kan läggas i fetstil kors på produktivitet.

Steg 5: Smart denormalisering

Båda våra problem kommer att lösas av ytterligare tabeller där vi kommer duplicera en del av datan, nödvändiga för att på dem bilda index som är lämpliga för våra uppgifter.
Messenger-databas (del 1): designa basramverket

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

Här har vi tillämpat två typiska tillvägagångssätt som används när vi skapar hjälptabeller:

  • Multiplicera rekord
    Med en inledande meddelandepost skapar vi flera uppföljningsposter i olika typer av register för olika ägare – både för avsändaren och för mottagaren. Men vart och ett av registren faller nu på indexet - trots allt, i ett typiskt fall vill vi bara se första sidan.
  • Unika rekord
    Varje gång du skickar ett meddelande inom ett specifikt ämne räcker det att kontrollera om en sådan post redan finns. Om inte, lägg till det i vår "ordbok".

I nästa del av artikeln kommer vi att prata om implementering av partitionering in i strukturen av vår databas.

Källa: will.com

Lägg en kommentar