Messengeri andmebaas (1. osa): baasraamistiku kujundamine

Kuidas saate ärinõudeid konkreetseteks andmestruktuurideks tõlkida, kasutades Messengeri andmebaasi nullist kujundamise näidet.

Messengeri andmebaas (1. osa): baasraamistiku kujundamine
Meie baas ei ole nii suur ja hajutatud, nagu VKontakte või Badoo, aga “nii et oli”, aga hea oli - funktsionaalne, kiire ja mahub ühte serverisse PostgreSQL - selleks, et saaksite juurutada näiteks teenuse eraldi eksemplari kuskile küljele.

Seetõttu ei käsitle me killustamise, replikatsiooni ja geograafiliselt hajutatud süsteemide küsimusi, vaid keskendume andmebaasis olevatele ahelalahendustele.

1. samm: mõned ettevõtte eripärad

Me ei kujunda oma sõnumivahetust abstraktselt, vaid integreerime selle keskkonda ettevõtte sotsiaalvõrgustik. See tähendab, et meie inimesed ei "lihtsalt ei suhtle", vaid suhtlevad omavahel teatud äriprobleemide lahendamise kontekstis.

Ja mis on ettevõtte ülesanded?.. Vaatame arendusosakonna juhataja Vassili näitel.

  • "Nikolai, selle ülesande jaoks vajame täna plaastrit!"
    See tähendab, et kirjavahetust saab pidada mõne kontekstis dokument.
  • "Kolya, kas sa lähed täna õhtul Dotasse?"
    See tähendab, et isegi üks vestluspartneri paar saab samaaegselt suhelda erinevatel teemadel.
  • "Peeter, Nikolai, otsi manusest uue serveri hinnakirja."
    Niisiis, üks sõnum võib olla mitu adressaati. Sel juhul võib sõnum sisaldada Lisatud failid.
  • "Semyon, vaata ka."
    Ja peaks olema võimalus sõlmida olemasolevat kirjavahetust kutsu uus liige.

Peatugem praegu sellel "ilmsete" vajaduste loendil.

Mõistmata probleemi rakenduslikku spetsiifikat ja sellele antud piiranguid, kujundada tõhus andmebaasi skeemi lahendamine on peaaegu võimatu.

2. samm: minimaalne loogikalülitus

Siiani toimib kõik väga sarnaselt e-kirjavahetusega – traditsioonilise äritööriistaga. Jah, "algoritmiliselt" on paljud äriprobleemid üksteisega sarnased, seetõttu on nende lahendamise tööriistad struktuurselt sarnased.

Parandame juba saadud olemisuhete loogilise diagrammi. Mudeli arusaadavuse hõlbustamiseks kasutame kõige primitiivsemat kuvamisvalikut ER mudelid ilma UML- või IDEF-märgete komplikatsioonideta:

Messengeri andmebaas (1. osa): baasraamistiku kujundamine

Meie näites on faili isik, dokument ja binaarne "keha" "välised" olemid, mis eksisteerivad iseseisvalt ilma meie teenuseta. Seetõttu tajume neid tulevikus lihtsalt UUID-i linkidena "kusagil".

Joonista diagrammid võimalikult lihtsad - enamik inimesi, kellele te neid näitate, ei ole UML/IDEF-i lugemise eksperdid. Aga kindlasti joonista.

3. samm: tabeli struktuuri visandamine

Tabelite ja väljade nimede kohtaPõldude ja tabelite “venekeelseid” nimetusi võib käsitleda erinevalt, kuid see on maitse asi. Kuna siin Tensoris välismaiseid arendajaid pole ja PostgreSQL võimaldab meil nimesid anda isegi hieroglüüfides, kui need jutumärkides, siis eelistame nimetada objekte üheselt ja selgelt, et ei tekiks lahknevusi.
Kuna paljud inimesed kirjutavad meile korraga sõnumeid, võivad mõned neist seda isegi teha võrguühenduseta, siis on kõige lihtsam variant kasutage identifikaatoritena UUID-sid mitte ainult välistele üksustele, vaid ka kõigile meie teenuses olevatele objektidele. Lisaks saab neid genereerida isegi kliendi poolel – see aitab meil toetada sõnumite saatmist, kui andmebaas on ajutiselt kättesaamatu ja kokkupõrke tõenäosus on äärmiselt väike.

Tabeli mustandstruktuur meie andmebaasis näeb välja järgmine:
Tabelid : 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
);

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

Kõige lihtsam on vormingu kirjeldamisel alustada ühendusgraafiku “lahti kerimist”. tabelitest, millele ei viidata ennast mitte kellelegi.

4. samm: uurige välja ebaselged vajadused

See on kõik, oleme loonud andmebaasi, kuhu saab kirjutada suurepäraselt ja kuidagi lugeda.

Paneme end oma teenuse kasutaja olukorda – mida me sellega peale hakata?

  • Viimased sõnumid
    see kronoloogiliselt järjestatud "minu" sõnumite register, mis põhineb erinevatel kriteeriumidel. Kus olen üks saajatest, kus autor, kus nad kirjutasid mulle ja ma ei vastanud, kus nad ei vastanud mulle, ...
  • Kirjavahetuses osalejad
    Kes selles pikas, pikas vestluses üldse osaleb?

Meie struktuur võimaldab meil lahendada mõlemad need probleemid "üldiselt", kuid mitte kiiresti. Probleem on selles, et sorteerimine toimub esimese ülesande raames ei saa indeksit luua, mis sobib igale osalejale (ja peate kõik kirjed välja võtma) ja teise lahendamiseks vajate ekstraktida kõik sõnumid sellel teemal.

Soovimatud kasutajaülesanded võivad olla paksus kirjas rist tootlikkusele.

5. samm: nutikas denormaliseerimine

Mõlemad meie probleemid lahendatakse täiendavate tabelitega, milles me seda teeme dubleerida osa andmetest, mis on vajalik neile meie ülesannete jaoks sobivate indeksite moodustamiseks.
Messengeri andmebaas (1. osa): baasraamistiku kujundamine

Tabelid : RU

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

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

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

Siin oleme abitabelite loomisel kasutanud kahte tüüpilist lähenemisviisi:

  • Kirjete korrutamine
    Ühe algse sõnumikirje abil loome eri tüüpi registritesse mitu järelkirjet erinevatele omanikele - nii saatjale kui ka saajale. Kuid kõik registrid langevad nüüd registrisse - tavaliselt tahame ju tavaliselt näha ainult esimest lehte.
  • Unikaalsed rekordid
    Iga kord, kui saadate sõnumi konkreetse teema raames, piisab, kui kontrollida, kas selline kirje on juba olemas. Kui ei, siis lisage see meie sõnaraamatusse.

Artikli järgmises osas räägime sellest partitsioonide rakendamine meie andmebaasi struktuuri.

Allikas: www.habr.com

Lisa kommentaar