„Messenger“ duomenų bazė (2 dalis): skaidymas „siekiant pelno“

Sėkmingai sukūrėme savo PostgreSQL duomenų bazės struktūrą korespondencijai saugoti, praėjo metai, vartotojai ją aktyviai pildo, o dabar joje yra milijonai įrašų, ir... kažkas pradėjo lėtėti.

„Messenger“ duomenų bazė (2 dalis): skaidymas „siekiant pelno“
Faktas yra tai, kad Didėjant lentelės dydžiui, didėja ir indeksų „gylis“. – nors ir logaritmiškai. Tačiau laikui bėgant tai priverčia serverį atlikti tas pačias skaitymo / rašymo užduotis apdoroti daug kartų daugiau duomenų puslapiųnei pradžioje.

Čia jis ateina į pagalbą skirstymas į dalis.

Norėčiau pažymėti, kad mes nekalbame apie dalijimąsi, ty duomenų paskirstymą tarp skirtingų duomenų bazių ar serverių. Nes net dalijant duomenis į šiek tiek serverių, neatsikratysite indeksų „brinkimo“ problemos laikui bėgant. Akivaizdu, kad jei galite sau leisti kiekvieną dieną pradėti eksploatuoti naują serverį, tai jūsų problemos jau visai nebegulės konkrečios duomenų bazės plotmėje.

Mes apsvarstysime ne konkrečius scenarijus, skirtus skaidymo „aparatinėje įrangoje“ įgyvendinimui, o patį požiūrį - ką ir kaip reikia „supjaustyti griežinėliais“, ir prie ko toks noras veda.

Koncepcija

Dar kartą apibrėžkime savo tikslą: norime užtikrinti, kad šiandien, rytoj ir po metų „PostgreSQL“ perskaitytų duomenų kiekis bet kokios skaitymo / rašymo operacijos metu išliks maždaug toks pat.

Bet kuriam chronologiškai sukauptus duomenis (pranešimai, dokumentai, žurnalai, archyvai, ...) yra natūralus skaidymo rakto pasirinkimas renginio data/laikas. Mūsų atveju toks įvykis yra žinutės išsiuntimo momentas.

Atminkite, kad vartotojai beveik visada dirbti tik su „naujausiais“. tokie duomenys - jie skaito naujausius pranešimus, analizuoja naujausius žurnalus,... Ne, žinoma, jie gali slinkti laiku atgal, bet tai daro labai retai.

Iš šių suvaržymų aišku, kad optimaliausias pranešimo sprendimas būtų "dienos" skyriai - juk mūsų vartotojas beveik visada skaitys tai, kas jam atėjo „šiandien“ ar „vakar“.

Jei per dieną rašome ir skaitome beveik tik vienoje sekcijoje, tai taip pat mums suteikia efektyvesnis atminties ir disko naudojimas - nes visi skyrių indeksai lengvai telpa į RAM, priešingai nei "dideli ir stori" visoje lentelėje.

žingsnis po žingsnio

Apskritai viskas, kas pasakyta aukščiau, skamba kaip vienas nuolatinis pelnas. Ir tai pasiekiama, bet dėl ​​to turėsime labai pasistengti - nes sprendimas padalinti vieną iš subjektų lemia poreikį „pamatyti“ susijusį.

Pranešimas, jo savybės ir projekcijos

Kadangi nusprendėme apkarpyti pranešimus pagal datas, prasminga taip pat suskirstyti nuo jų priklausančius objektus-ypatybes (pridedami failai, gavėjų sąrašas) ir taip pat pagal pranešimo datą.

Kadangi viena iš mūsų tipiškų užduočių yra būtent pranešimų registrų (neskaitytų, gaunamų, visų) peržiūra, taip pat logiška juos „įtraukti“ į skaidymą pagal pranešimų datas.

„Messenger“ duomenų bazė (2 dalis): skaidymas „siekiant pelno“

Pridedame skaidymo raktą (pranešimo datą) į visas lenteles: gavėjus, failą, registrus. Jūs neprivalote jo pridėti prie paties pranešimo, bet naudokite esamą DateTime.

Tematika

Kadangi kelioms žinutėms yra tik viena tema, negalima jos „įkirpti“ į tą patį modelį, reikia pasikliauti kažkuo kitu. Mūsų atveju tai idealu pirmosios korespondencijos žinutės data - tai yra temos sukūrimo momentas.

„Messenger“ duomenų bazė (2 dalis): skaidymas „siekiant pelno“

Pridėkite skaidymo raktą (temos datą) į visas lenteles: tema, dalyvis.

Bet dabar turime dvi problemas vienu metu:

  • Kuriame skyriuje turėčiau ieškoti pranešimų šia tema?
  • Kuriame skyriuje turėčiau ieškoti temos iš pranešimo?

Žinoma, galime ir toliau ieškoti visuose skyriuose, bet tai bus labai liūdna ir panaikins visus mūsų laimėjimus. Todėl, norėdami žinoti, kur tiksliai ieškoti, sukursime logines nuorodas / nuorodas į skyrius:

  • pridėsime žinutėje temos datos lauką
  • papildykime temą pranešimo data nustatyta ši korespondencija (gali būti atskira lentelė arba datų masyvas)

„Messenger“ duomenų bazė (2 dalis): skaidymas „siekiant pelno“

Kadangi kiekvienos atskiros korespondencijos žinučių datų sąraše bus nedaug modifikacijų (juk beveik visos žinutės patenka į 1-2 gretimas dienas), aš sutelksiu dėmesį į šį variantą.

Iš viso mūsų duomenų bazės struktūra buvo tokia, atsižvelgiant į skaidymą:

Lentelės: RU, jei jums nepatinka kirilicos abėcėlė lentelių/laukų pavadinimuose, geriau nežiūrėti

-- секции по дате сообщения
CREATE TABLE "Сообщение_YYYYMMDD"(
  "Сообщение"
    uuid
      PRIMARY KEY
, "Тема"
    uuid
, "ДатаТемы"
    date
, "Автор"
    uuid
, "ДатаВремя" -- используем как дату
    timestamp
, "Текст"
    text
);

CREATE TABLE "Адресат_YYYYMMDD"(
  "ДатаСообщения"
    date
, "Сообщение"
    uuid
, "Персона"
    uuid
, PRIMARY KEY("Сообщение", "Персона")
);

CREATE TABLE "Файл_YYYYMMDD"(
  "ДатаСообщения"
    date
, "Файл"
    uuid
      PRIMARY KEY
, "Сообщение"
    uuid
, "BLOB"
    uuid
, "Имя"
    text
);

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

-- секции по дате темы
CREATE TABLE "Тема_YYYYMMDD"(
  "ДатаТемы"
    date
, "Тема"
    uuid
      PRIMARY KEY
, "Документ"
    uuid
, "Название"
    text
);

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

CREATE TABLE "ДатыСообщенийТемы_YYYYMMDD"(
  "ДатаТемы"
    date
, "Тема"
    uuid
      PRIMARY KEY
, "Дата"
    date
);

Sutaupyk gražų centą

Na, o jei nenaudosime klasikinis skirstymo variantas Remdamiesi lauko reikšmių pasiskirstymu (per trigerius ir paveldėjimą arba PARTITION BY) ir „rankiniu būdu“ programos lygiu, pastebėsite, kad skaidymo rakto reikšmė jau yra saugoma pačios lentelės pavadinime.

Taigi, jei esate toks Ar labai nerimaujate dėl saugomų duomenų kiekio?, tuomet galite atsikratyti šių „papildomų“ laukų ir nurodyti konkrečias lenteles. Tiesa, visus pasirinkimus iš kelių skyrių tokiu atveju teks perkelti į paraiškos pusę.

Šaltinis: www.habr.com

Добавить комментарий