Baza podatkov Messenger (2. del): particioniranje "za dobiček"

Uspešno smo oblikovali strukturo baze podatkov PostgreSQL za shranjevanje korespondence, minilo je leto dni, uporabniki jo aktivno polnijo in zdaj vsebuje milijone zapisov, in ... nekaj se je začelo upočasnjevati.

Baza podatkov Messenger (2. del): particioniranje "za dobiček"
Dejstvo je, da Z večanjem velikosti tabele se povečuje tudi "globina" indeksov. - čeprav logaritemsko. Toda sčasoma to prisili strežnik, da izvaja iste naloge branja/pisanja obdela velikokrat več strani podatkovkot na začetku.

Tukaj pride na pomoč razdeljevanje.

Naj opozorim, da ne govorimo o shardingu, torej o distribuciji podatkov med različnimi bazami ali strežniki. Ker tudi delitev podatkov na nekateri strežnikov, se sčasoma ne boste znebili problema »nabrekanja« indeksov. Jasno je, da če si lahko privoščite, da vsak dan zaženete nov strežnik, potem vaše težave sploh ne bodo več v ravnini določene baze podatkov.

Ne bomo upoštevali posebnih skriptov za izvedbo particioniranja "v strojni opremi", temveč sam pristop - kaj in kako je treba "razrezati na rezine" in do česa takšna želja vodi.

Koncept

Še enkrat opredelimo naš cilj: zagotoviti želimo, da bo danes, jutri in čez eno leto količina podatkov, ki jih prebere PostgreSQL med katero koli operacijo branja/pisanja, ostala približno enaka.

Za katero koli kronološko nabranih podatkov (sporočila, dokumenti, dnevniki, arhivi, ...) naravna izbira kot particijski ključ je datum/čas dogodka. V našem primeru je tak dogodek trenutek pošiljanja sporočila.

Upoštevajte, da uporabniki skoraj vedno delo samo z "najnovejšimi". takšni podatki - berejo zadnja sporočila, analizirajo zadnje dnevnike,... Ne, seveda se lahko pomaknejo še dlje v preteklost, vendar to počnejo zelo redko.

Iz teh omejitev je jasno, da bi bila optimalna rešitev sporočila "dnevne" rubrike - navsezadnje bo naš uporabnik skoraj vedno prebral, kar mu je prišlo "danes" ali "včeraj".

Če čez dan pišemo in beremo skoraj samo v enem delu, potem nam tudi to daje učinkovitejša uporaba pomnilnika in diska - ker se vsi indeksi razdelkov zlahka prilegajo v RAM, v nasprotju z "velikimi in debelimi" po vsej tabeli.

korak za korakom

Na splošno se vse zgoraj povedano sliši kot en neprekinjen dobiček. In uresničljiva, a za to se bomo morali potruditi – saj odločitev o razdelitvi ene od entitet vodi do potrebe po "žaganju" povezane.

Sporočilo, njegove lastnosti in projekcije

Ker smo se odločili razrezati sporočila po datumih, je smiselno razdeliti tudi od njih odvisne entitete-lastnosti (priložene datoteke, seznam prejemnikov) in tudi po datumu sporočila.

Ker je ena izmed naših tipičnih nalog prav pregledovanje registrov sporočil (neprebranih, dohodnih, vseh), je logično tudi, da jih “vvlečemo” v razdelitev po datumih sporočil.

Baza podatkov Messenger (2. del): particioniranje "za dobiček"

Vsem tabelam dodamo particijski ključ (datum sporočila): prejemniki, datoteka, registri. Ni vam ga treba dodati samemu sporočilu, ampak uporabite obstoječi datum in čas.

teme

Ker obstaja le ena tema za več sporočil, je nikakor ne gre "rezati" v isti model, ampak se je treba zanesti na nekaj drugega. V našem primeru je idealen datum prvega sporočila v korespondenci — torej trenutek nastanka, pravzaprav teme.

Baza podatkov Messenger (2. del): particioniranje "za dobiček"

Dodajte razdelitveni ključ (datum teme) v vse tabele: tema, udeleženec.

Toda zdaj imamo dve težavi hkrati:

  • V katerem razdelku naj iščem sporočila na temo?
  • V kateri rubriki naj iščem temo iz sporočila?

Seveda lahko nadaljujemo z iskanjem v vseh razdelkih, vendar bo to zelo žalostno in bo izničilo vse naše dobitke. Zato, da bi vedeli, kje točno iskati, bomo naredili logične povezave/kazalce na odseke:

  • bomo dodali v sporočilu polje datuma teme
  • dopolnimo temo nastavljen datum sporočila ta korespondenca (lahko je ločena tabela ali niz datumov)

Baza podatkov Messenger (2. del): particioniranje "za dobiček"

Ker bo seznam datumov sporočil za vsako posamezno korespondenco malo spremenjen (navsezadnje skoraj vsa sporočila padejo na 1-2 sosednja dneva), se bom osredotočil na to možnost.

Skupaj je struktura naše baze podatkov ob upoštevanju razdelitve dobila naslednjo obliko:

Tabele: RU, če imate odpor do cirilice v imenih tabel/polj, je bolje, da ne iščete

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

Prihranite lep peni

No, kaj pa če ne uporabljamo klasična možnost rezanja na podlagi porazdelitve vrednosti polj (prek sprožilcev in dedovanja ali PARTITION BY) in »ročno« na ravni aplikacije boste opazili, da je vrednost particijskega ključa že shranjena v imenu same tabele.

Torej, če ste tako Vas zelo skrbi količina shranjenih podatkov?, potem se lahko znebite teh "dodatnih" polj in naslovite določene tabele. Res je, da bo treba vse izbire iz več razdelkov v tem primeru prenesti na stran aplikacije.

Vir: www.habr.com

Dodaj komentar