Messenger baza podataka (2. dio): particioniranje “za profit”

Uspješno smo dizajnirali strukturu naše PostgreSQL baze podataka za pohranjivanje korespondencije, prošla je godina dana, korisnici je aktivno popunjavaju, a sada sadrži milijuni zapisa, i... nešto je počelo usporavati.

Messenger baza podataka (2. dio): particioniranje “za profit”
Činjenica je da Kako raste veličina tablice, tako raste i "dubina" indeksa. - iako logaritamski. Ali s vremenom to prisiljava poslužitelj da obavlja iste zadatke čitanja/pisanja obraditi višestruko više stranica podatakanego na početku.

Tu dolazi u pomoć sekcioniranje.

Napominjem da ne govorimo o šardingu, odnosno distribuciji podataka između različitih baza podataka ili poslužitelja. Jer čak i dijeljenje podataka na više poslužitelja, nećete se riješiti problema "bubrenja" indeksa tijekom vremena. Jasno je da ako si možete priuštiti puštanje u rad novog poslužitelja svaki dan, onda vaši problemi više uopće neće ležati u ravni određene baze podataka.

Nećemo razmatrati specifične skripte za implementaciju particioniranja "u hardveru", već sam pristup - što i kako treba "izrezati na kriške" i čemu takva želja vodi.

Koncept

Definirajmo još jednom naš cilj: želimo biti sigurni da će danas, sutra i za godinu dana količina podataka koje PostgreSQL pročita tijekom bilo koje operacije čitanja/pisanja ostati približno ista.

Za bilo koje kronološki prikupljeni podaci (poruke, dokumenti, zapisnici, arhive, ...) prirodan izbor kao particioni ključ je datum/vrijeme događaja. U našem slučaju takav je događaj trenutku slanja poruke.

Imajte na umu da korisnici gotovo uvijek raditi samo s "najnovijim". takve podatke - čitaju najnovije poruke, analiziraju najnovije zapise,... Ne, naravno, mogu se pomicati dalje u prošlost, ali to čine vrlo rijetko.

Iz ovih ograničenja jasno je da bi optimalno rješenje poruke bilo "dnevne" rubrike - uostalom, naš će korisnik gotovo uvijek pročitati ono što mu je došlo “danas” ili “jučer”.

Ako tijekom dana pišemo i čitamo gotovo samo u jednom dijelu, onda nam i to daje učinkovitije korištenje memorije i diska - budući da svi indeksi sekcija lako stanu u RAM, za razliku od onih "velikih i debelih" u cijeloj tablici.

korak po korak

Općenito, sve gore rečeno zvuči kao jedan kontinuirani profit. I to je ostvarivo, ali za ovo ćemo se morati dobro potruditi – jer odluka o podjeli jednog od entiteta dovodi do potrebe da se "prepili" povezano.

Poruka, njezina svojstva i projekcije

Budući da smo odlučili poruke rezati po datumima, ima smisla podijeliti i entitete-svojstva koja o njima ovise (priložene datoteke, popis primatelja), i također prema datumu poruke.

Budući da je jedan od naših tipičnih zadataka upravo pregled registara poruka (nepročitanih, dolaznih, svih), također je logično da ih “uvučemo” u particiju po datumima poruka.

Messenger baza podataka (2. dio): particioniranje “za profit”

Dodajemo particioni ključ (datum poruke) u sve tablice: primatelji, datoteka, registri. Ne morate ga dodati u samu poruku, već koristite postojeći DateTime.

Teme

Budući da postoji samo jedna tema za nekoliko poruka, nema načina da je “srežete” u istom modelu, morate se osloniti na nešto drugo. U našem slučaju to je idealno datum prve poruke u korespondenciji — odnosno trenutak nastanka, zapravo, teme.

Messenger baza podataka (2. dio): particioniranje “za profit”

Dodajte particioni ključ (datum teme) svim tablicama: tema, sudionik.

Ali sada imamo dva problema odjednom:

  • U kojem odjeljku trebam tražiti poruke o temi?
  • U kojoj rubrici da tražim temu iz poruke?

Možemo, naravno, nastaviti tražiti u svim odjeljcima, ali to će biti vrlo tužno i poništit će sve naše dobitke. Stoga, kako bismo znali gdje točno tražiti, napravit ćemo logične poveznice/pokazivače na odjeljke:

  • dodat ćemo u poruci polje datuma teme
  • dopunimo temu postavljen datum poruke ovo dopisivanje (može biti zasebna tablica ili niz datuma)

Messenger baza podataka (2. dio): particioniranje “za profit”

Budući da će biti nekoliko izmjena na popisu datuma poruka za svaku pojedinačnu korespondenciju (uostalom, gotovo sve poruke padaju na 1-2 susjedna dana), usredotočit ću se na ovu opciju.

Ukupno je struktura naše baze podataka imala sljedeći oblik, uzimajući u obzir particije:

Tablice: RU, ako imaš averziju prema ćirilici u nazivima tabela/polja, bolje da ne gledaš

-- секции по дате сообщения
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
);

Uštedite priličan novčić

Pa, što ako ne koristimo klasična opcija rezanja na temelju distribucije vrijednosti polja (putem okidača i nasljeđivanja ili PARTITION BY), te “ručno” na razini aplikacije, primijetit ćete da je vrijednost particionog ključa već pohranjena u nazivu same tablice.

Pa ako ste tako Jeste li jako zabrinuti zbog količine pohranjenih podataka?, tada se možete riješiti ovih "dodatnih" polja i adresirati određene tablice. Istina, svi odabiri iz nekoliko odjeljaka u ovom slučaju morat će se prenijeti na stranu aplikacije.

Izvor: www.habr.com

Dodajte komentar