Baza de date Messenger (partea 1): proiectarea cadrului de bază

Cum puteți traduce cerințele de afaceri în structuri de date specifice folosind exemplul de proiectare a unei baze de date messenger de la zero.

Baza de date Messenger (partea 1): proiectarea cadrului de bază
Baza noastră nu va fi la fel de mare și distribuită, ca VKontakte sau Badoo, dar „așa că a fost”, dar a fost bun - funcțional, rapid și se potrivesc pe un singur server PostgreSQL - astfel încât să puteți implementa o instanță separată a serviciului undeva în lateral, de exemplu.

Prin urmare, nu ne vom referi la problemele de fragmentare, replicare și sisteme geo-distribuite, ci ne vom concentra pe soluțiile de circuit din interiorul bazei de date.

Pasul 1: Câteva detalii de afaceri

Nu ne vom proiecta mesajele în mod abstract, ci le vom integra în mediu rețea socială corporativă. Adică, oamenii noștri nu „doar corespunde”, ci comunică între ei în contextul rezolvării anumitor probleme de afaceri.

Și care sunt sarcinile unei afaceri?.. Să ne uităm la exemplul lui Vasily, șeful departamentului de dezvoltare.

  • „Nikolai, pentru această sarcină avem nevoie de un plasture astăzi!”
    Aceasta înseamnă că corespondența poate fi efectuată în contextul unora document.
  • „Kolya, mergi la Dota în seara asta?”
    Adică, chiar și o pereche de interlocutori poate comunica simultan pe diverse teme.
  • „Peter, Nikolay, caută în atașament lista de prețuri pentru noul server.”
    Deci, un mesaj poate avea mai mulți destinatari. În acest caz, mesajul poate conține Fișiere atașate.
  • „Semyon, aruncă o privire și tu.”
    Și ar trebui să existe o oportunitate de a intra în corespondența existentă invita un nou membru.

Să ne oprim deocamdată pe această listă de nevoi „evidente”.

Fără a înțelege specificul aplicat al problemei și limitările date acesteia, proiectează efectiv schema bazei de date pentru a o rezolva este aproape imposibil.

Pasul 2: Circuit logic minim

Până acum, totul funcționează foarte asemănător cu corespondența prin e-mail - un instrument tradițional de afaceri. Da, „din punct de vedere algoritmic” multe probleme de afaceri sunt similare între ele, prin urmare instrumentele pentru rezolvarea lor vor fi similare structural.

Să reparăm diagrama logică deja obținută a relațiilor dintre entități. Pentru a face modelul nostru mai ușor de înțeles, vom folosi cea mai primitivă opțiune de afișare Modele ER fără complicațiile notațiilor UML sau IDEF:

Baza de date Messenger (partea 1): proiectarea cadrului de bază

În exemplul nostru, persoana, documentul și „corpul” binar al fișierului sunt entități „externe” care există independent fără serviciul nostru. Prin urmare, le vom percepe pur și simplu în viitor ca niște link-uri „undeva” prin UUID.

A desena diagrame cât mai simple - majoritatea oamenilor cărora le vei arăta nu sunt experți în citirea UML/IDEF. Dar asigurați-vă că desenați.

Pasul 3: Schițarea structurii tabelului

Despre numele tabelelor și câmpurilorNumele „rusești” ale câmpurilor și tabelelor pot fi tratate diferit, dar aceasta este o chestiune de gust. Deoarece aici la Tensor nu există dezvoltatori străini, iar PostgreSQL ne permite să dăm nume chiar și în hieroglife, dacă acestea cuprinse între ghilimele, atunci preferăm să numim obiectele fără ambiguitate și clar, astfel încât să nu existe discrepanțe.
Deoarece mulți oameni ne scriu mesaje deodată, unii dintre ei ar putea chiar să facă acest lucru deconectat, atunci cea mai simplă opțiune este utilizați UUID-urile ca identificatori nu numai pentru entitățile externe, ci și pentru toate obiectele din interiorul serviciului nostru. Mai mult, ele pot fi generate chiar și din partea clientului - acest lucru ne va ajuta să acceptăm trimiterea de mesaje atunci când baza de date este temporar indisponibilă, iar probabilitatea unei coliziuni este extrem de scăzută.

Structura schiță a tabelului din baza noastră de date va arăta astfel:
Tabele: 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
);

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

Cel mai simplu lucru atunci când descrieți un format este să începeți „desfășurarea” graficului conexiunii din tabele care nu sunt referite ei înșiși pentru nimeni.

Pasul 4: Aflați nevoi neevidente

Gata, am conceput o bază de date în care poți scrie perfect și oarecum a citi.

Să ne punem în pielea utilizatorului serviciului nostru - ce vrem să facem cu el?

  • Ultimele mesaje
    Aceasta sortate cronologic un registru al mesajelor „mei” bazat pe diverse criterii. Unde sunt unul dintre destinatari, unde sunt autorul, unde mi-au scris și nu am răspuns, unde nu mi-au răspuns, ...
  • Participanții la corespondență
    Cine participă măcar la această discuție lungă, lungă?

Structura noastră ne permite să rezolvăm ambele probleme „în general”, dar nu rapid. Problema este că pentru sortarea în cadrul primei sarcini nu se poate crea index, potrivit pentru fiecare dintre participanți (și va trebui să extrageți toate înregistrările), iar pentru a le rezolva pe a doua aveți nevoie extrage toate mesajele pe această temă.

Sarcinile utilizatorului neintenționate pot pune bold cruce pe productivitate.

Pasul 5: Denormalizare inteligentă

Ambele probleme vor fi rezolvate prin tabele suplimentare în care vom face duplicat o parte a datelor, necesare pentru a forma pe ele indici potriviți sarcinilor noastre.
Baza de date Messenger (partea 1): proiectarea cadrului de bază

Tabele: RU

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

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

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

Aici am aplicat două abordări tipice folosite la crearea tabelelor auxiliare:

  • Înmulțirea înregistrărilor
    Folosind o singură înregistrare inițială a mesajului, creăm mai multe înregistrări ulterioare în diferite tipuri de registre pentru diferiți proprietari - atât pentru expeditor, cât și pentru destinatar. Dar fiecare dintre registre cade acum pe index - la urma urmei, într-un caz tipic, vom dori să vedem doar prima pagină.
  • Înregistrări unice
    De fiecare dată când trimiteți un mesaj într-un anumit subiect, este suficient să verificați dacă o astfel de intrare există deja. Dacă nu, adăugați-l în „dicționarul”.

În următoarea parte a articolului vom vorbi despre implementarea partiționării în structura bazei noastre de date.

Sursa: www.habr.com

Adauga un comentariu