Me oleme edukalt projekteerinud meie PostgreSQL andmebaasi struktuuri vestluste salvestamiseks, aasta on möödas ja kasutajad tĂ€idavad seda aktiivselt, nĂŒĂŒd on seal juba miljoneid kirjeid, ja⊠midagi hakkas aeglasemalt minema.
- Jagu 2: sektsioneerime âreaalajasâ

Asi on selles, et Kuna tabeli maht suureneb, suureneb ka indeksite "sĂŒgavus" â kuigi logaritmiliselt. Kuid aja jooksul sunnib see serverit tĂ€itma samu lugemise/kirjutamise ĂŒlesandeid kĂ€sitlema tĂ€htselt rohkem andmelehti, kui alguses.
Siinkohal tuleb appi partitsioneerimine.
Tuleb mÀrkida, et rÀÀgime mitte shardimisest, st andmete jaotamisest erinevate andmebaaside vÔi serverite vahel. Sest isegi kui te jagate andmed mÔningaid serverite vahel, ei pÀÀse te ajapikku esineva "indeksite paisumise" probleemist. On selge, et kui saate iga pÀev uue serveri juurutada, siis teie probleemid ei jÀÀ seotud konkreetse andmebaasi tasandiga.
Me vaatame mitte konkreetseid skripte, et teostada partitsioneerimist "rauda", vaid lĂ€henemist â mida ja kuidas tuleks "tĂŒkeldada" ning mida see soov kaasa toob.
KĂ€siteema
Kordame meie eesmÀrki: soovime seda, et tÀna, homme ja aasta pÀrast jÀÀks PostgreSQL loetavate andmete hulk igasuguste lugemise/kirjutamise operatsioonide kÀigus enam-vÀhem samaks.
KĂ€esolevate jaoks ajal pooltugevdus andmetele (sĂ”numid, dokumendid, logid, arhiivid, âŠ) on partitsioneerimise vĂ”tmekohaks loomulikult sĂŒndmuse kuupĂ€ev/aeg. Meie puhul on selliseks sĂŒndmuseks sĂ”numi saatmise hetk.
MĂ€rkasime, et kasutajad töötavad peaaegu alati ainult "viimastega" selliste andmete â loevad viimaseid sĂ”numeid, analĂŒĂŒsivad viimaseid logisid,⊠Ei, loomulikult vĂ”ivad nad kerida ka ajas tagasi, kuid teevad seda vĂ€ga harva.
Nendest piirangutest on selge, et parim lahendus sĂ”numite jaoks oleks "pĂ€evaste" sektsioonide loomine â sest peaaegu alati loeb meie kasutaja seda, mis tuli "tĂ€na" vĂ”i "eile".
Kui me pĂ€eva jooksul kirjutame ja loeme peamiselt vaid ĂŒhes sektsioonis, siis see annab meile ka efektiivsema mĂ€lu ja ketta kasutamise â kuna kĂ”ik sektsiooni indeksid mahuvad hĂ”lpsasti mĂ€llu, erinevalt "suurtest ja paksudest" kogu tabelis.
step-by-step
Ăldiselt kĂ”lab kĂ”ik, mis eespool öeldud, nagu suur kasum. Ja see on saavutatav, kuid selleks peame korralikult vaeva nĂ€gema â sest ĂŒks olendite sektsioneerimise lahendus toob kaasa vajaduse «jagada» ka need, mis sellega seotud.
SÔnum, selle omadused ja projektsioonid
Kuna otsustasime sÔnumeid kuupÀevade pÔhjal jagada, on mÔistlik jagada ka sÔltuvad omadused (lisatud failid, adressaatide nimekiri) ja ka sÔnumi kuupÀeva pÔhjal.
Kuna ĂŒks meie tĂŒĂŒpilisi ĂŒlesandeid on sĂ”numite registrite ĂŒlevaatamine (lugemata, sissetulevad, kĂ”ik), on loogiline, et need «kaasata» sĂ”numite kuupĂ€evade pĂ”hjal sektsioneerimisse.

Lisame sektsioneerimise vÔtme (sÔnumi kuupÀeva) kÔikidesse tabelitesse: adressaadid, fail, registrid. SÔnumisse ise vÔib seda mitte lisada, vaid kasutada olemasolevat DateTime.
Teemad
Kuna teema on mitme sĂ”numi kohta, ei saa seda sama mudeli jĂ€rgi enam jagada, peame toetuma millelegi muule. Meie puhul sobib ideaalselt esimese sĂ”numi kuupĂ€ev vestluses â seega hetke loomine, tegelikult teema.

Lisame sektsioneerimise vÔtme (teema kuupÀeva) kÔikidesse tabelitesse: teema, osaleja.
Kuid nĂŒĂŒd tekib meil kohe kaks probleemi:
- milles sektsioonis otsida sÔnumeid teema jÀrgi?
- milles sektsioonis otsida teemat sÔnumist?
Saame muidugi jÀtkata otsimist kÔigis sektsioonides, kuid see oleks vÀga kurb ja nulliks kÔik meie kasud. SeetÔttu, et teada saada, kus otsida, loome loogilised lingid/viidatud sektsioonid:
- sÔnumisse lisame vÀlja teema kuupÀeva
- teemale lisame sÔnumite kuupÀevade komplekti selle vestluse kohta (vÔib olla eraldi tabelina vÔi kuupÀevase massiivina)

Kuna eraldi vestlusele sÔnumite kuupÀevade nimekiri on vÀike (peaaegu kÔik sÔnumid langevad 1-2 jÀrgneva pÀeva sisse), pean peatuma just sellisel variandil.
KokkuvÔttes on meie andmebaasi struktuur selline, arvestades sektsioneerimist:
Tabelid: RU, kui kirillitsast pealkirjades/xmlid/pÔldudes kÔrvalehoidmine, siis pole parem vaadata
-- osakonnad sÔnumi kuupÀeva jÀrgi
CREATE TABLE "SÔnum_YYYYMMDD"(
"SÔnum"
uuid
PRIMARY KEY
, "Teema"
uuid
, "KuupÀevTeema"
date
, "Autor"
uuid
, "KuupÀevAeg" -- kasutame kuupÀevana
timestamp
, "Tekst"
text
);
CREATE TABLE "Saaja_YYYYMMDD"(
"KuupÀevSÔnum"
date
, "SÔnum"
uuid
, "Isik"
uuid
, PRIMARY KEY("SÔnum", "Isik")
);
CREATE TABLE "Fail_YYYYMMDD"(
"KuupÀevSÔnum"
date
, "Fail"
uuid
PRIMARY KEY
, "SÔnum"
uuid
, "BLOB"
uuid
, "Nimi"
text
);
CREATE TABLE "SÔnumiteRegistr_YYYYMMDD"(
"KuupÀevSÔnum"
date
, "Omandaja"
uuid
, "RegistriTĂŒĂŒp"
smallint
, "KuupÀevAeg"
timestamp
, "SÔnum"
uuid
, PRIMARY KEY("Omandaja", "RegistriTĂŒĂŒp", "SĂ”num")
);
CREATE INDEX ON "SĂ”numiteRegistr_YYYYMMDD"("Omandaja", "RegistriTĂŒĂŒp", "KuupĂ€evAeg" DESC);
-- osakonnad teema kuupÀeva jÀrgi
CREATE TABLE "Teema_YYYYMMDD"(
"KuupÀevTeema"
date
, "Teema"
uuid
PRIMARY KEY
, "Dokument"
uuid
, "Pealkiri"
text
);
CREATE TABLE "TeemaOsaline_YYYYMMDD"(
"KuupÀevTeema"
date
, "Teema"
uuid
, "Isik"
uuid
, PRIMARY KEY("Teema", "Isik")
);
CREATE TABLE "TeemaSÔnumiteKuupÀevad_YYYYMMDD"(
"KuupÀevTeema"
date
, "Teema"
uuid
PRIMARY KEY
, "KuupÀev"
date
);
SÀÀstame raha
Aga kui me ei kasuta vÀli vÀÀrtuste jaotuse pÔhjal (triggereid ja pÀrandamist vÔi PARTITION BY), vaid teeme seda "kÀtega" rakenduse tasemel, siis vÔib mÀrgata, et sektsioneerimisvÔti on juba talletatud tabeli nimetuses.
SeetĂ”ttu, kui te olete nii muretsenud salvestatud andmete hulga pĂ€rast, siis neist "ĂŒlearustest" vĂ€ljadest vĂ”ib ka loobuda ja pöörduda otseselt konkreetsete tabelite poole. TĂ”si, kĂ”ik valikud mitmest sektsioonist tuleb sel juhul rakenduse tasemele viia.
Allikas: habr.com
