Baza e të dhënave të mesazheve (përgj.2): seksionojmë «në kohë reale»

Kemi projektuar me sukses strukturĂ«n e bazĂ«s sonĂ« tĂ« PostgreSQL pĂ«r ruajtjen e bisedave, ka kaluar njĂ« vit, pĂ«rdoruesit e mbushin atĂ« aktivisht, kĂ«tu ka tashmĂ« miliona regjistrime, dhe
 diçka ka filluar tĂ« ngadalĂ«sohet.

Baza e të dhënave të mesazheve (përgj.2): seksionojmë «në kohë reale»
Çështja Ă«shtĂ« se me rritjen e volumit tĂ« tryezĂ«s rritet edhe "thellĂ«sia" e indekseve — ndonĂ«se nĂ« mĂ«nyrĂ« logarithmike. Por me kalimin e kohĂ«s kjo e detyron serverin tĂ« pĂ«rpunojĂ« pĂ«r tĂ« njĂ«jtat detyra tĂ« leximit/shkrimit shumĂ« mĂ« tepĂ«r faqe tĂ« dhĂ«nash, se sa nĂ« fillim.

Këtu është në ndihmë sekcionimi.

VĂ«rej se nuk po flas pĂ«r sharding, pra shpĂ«rndarjen e tĂ« dhĂ«nave midis bazave tĂ« ndryshme ose serverĂ«ve. Sepse, edhe nĂ«se ndan tĂ« dhĂ«nat nĂ« disa serverĂ«t, nuk do tĂ« eleminosh dot problemin e "zmadhojnĂ«" indekseve me kalimin e kohĂ«s. ËshtĂ« e qartĂ« se nĂ«se mund tĂ« lejojmĂ« çdo ditĂ« tĂ« fusim nĂ« funksion njĂ« server tĂ« ri, atĂ«herĂ« problemet tona do tĂ« kalonin nĂ« njĂ« nivel krejt tjetĂ«r, jashtĂ« asaj tĂ« veçantĂ«s sĂ« BDs.

Ne do tĂ« shqyrtojmĂ« jo skenarĂ«t e veçantĂ« pĂ«r implementimin e sekcionimit "nĂ« harduer", por qasjen vetĂ« — se çfarĂ« dhe si duhet "prerĂ« nĂ« copa", dhe çfarĂ« tĂ« tilla dĂ«shira sjell.

Koncepti

Një herë tjetër le të përcaktojmë qëllimin tonë: ne dëshirojmë që dhe sot, dhe nesër, dhe pas një viti numri i të dhënave PostgreSQL të lexueshme gjatë çdo operacioni leximi/shkrimi të mbetet përafërsisht i njëjtë.

PĂ«r çdo lloj tĂ« dhĂ«nash qĂ« akumulohet nĂ« mĂ«nyrĂ« kronologjike (mesazhe, dokumente, loge, arkiva, 
) zgjedhja natyrale si çelĂ«si pĂ«r ndarjen Ă«shtĂ« data/koha e ngjarjes. NĂ« rastin tonĂ«, kjo ngjarje Ă«shtĂ« momentin e dĂ«rgimit tĂ« mesazhit.

VĂ«rej se pĂ«rdoruesit zakonisht punojnĂ« vetĂ«m me "tĂ« fundit" tĂ« dhĂ«na tĂ« tilla — lexojnĂ« mesazhet mĂ« tĂ« fundit, analizojnĂ« loget mĂ« tĂ« fundit,
 Jo, natyrisht, ata mund tĂ« shfletojnĂ« edhe mĂ« ngadalĂ« prapa nĂ« kohĂ«, por e bĂ«jnĂ« atĂ« shumĂ« rrallĂ«.

Nga kĂ«to kufizime bĂ«het e qartĂ« se zgjidhja mĂ« optimale pĂ«r mesazhet do tĂ« jenĂ« "seksionet pĂ«r ditĂ«" — sepse pothuajse gjithmonĂ« pĂ«rdoruesi ynĂ« do tĂ« lexojĂ« atĂ« qĂ« i ka ardhur "sot" ose "dje".

NĂ«se gjatĂ« ditĂ«s shkruajmĂ« dhe lexojmĂ« nĂ« mĂ«nyrĂ« praktike vetĂ«m nĂ« njĂ« seksion, atĂ«herĂ« kjo na japin gjithashtu pĂ«rdorim mĂ« efektiv tĂ« memories dhe diskut — sepse tĂ« gjithĂ« indeksat e seksionit lehtĂ« mund tĂ« mbahen nĂ« RAM, nĂ« krahasim me "tĂ« mĂ«dhenjtĂ« dhe tĂ« rĂ«ndĂ«" nĂ« tĂ« gjithĂ« tryezĂ«n.

hapi-pas-hapi

Dhe pra, gjithĂ« çka u tha mĂ« lart tingĂ«llon si njĂ« fitim i pashembullt. Dhe ai Ă«shtĂ« i arritshĂ«m, por pĂ«r kĂ«tĂ« duhet tĂ« punojmĂ« mirĂ« — sepse zgjidhja pĂ«r tĂ« sekcionuar njĂ« nga entitetet e krijon nevojĂ«n pĂ«r "prerjen" e entiteteve tĂ« lidhura me tĂ«.

Mesazhi, vetitë e tij dhe projekcionet

Përderisa vendosëm të presim mesazhet sipas datave, ka sens të ndajmë gjithashtu edhe entitetet e varura prej tyre (skedarë të bashkangjitur, lista e marrësve), dhe po ashtu sipas datës së mesazhit.

Duke qenë se një nga detyrat tona tipike është pikërisht shikimi i regjistrave të mesazheve (të pa lexuara, të ardhshme, të gjitha), është logjike që ato gjithashtu të "përfshihen" në sekcionimin sipas datave të mesazheve.

Baza e të dhënave të mesazheve (përgj.2): seksionojmë «në kohë reale»

Shtojmë çelësin e sekcionimit (datën e mesazhit) në të gjitha tryezat: marrësit, skedari, regjistrat. Në mesazh vetë nuk mund të shtojmë, por të përdorim Datën e Koha ekzistuese.

Temat

Duke qenĂ« se tema Ă«shtĂ« njĂ« pĂ«r disa mesazhe, e "prerĂ«" nĂ« modelin e njĂ«jtĂ« nuk do tĂ« jetĂ« e mundur, duhet tĂ« mbĂ«shtetemi nĂ« diçka tjetĂ«r. NĂ« rastin tonĂ«, pĂ«rkryer pĂ«r kĂ«tĂ« Ă«shtĂ« data e mesazhit tĂ« parĂ« nĂ« bisedĂ« — pra momenti i krijimit, vetĂ« tema.

Baza e të dhënave të mesazheve (përgj.2): seksionojmë «në kohë reale»

Shtojmë çelësin e sekcionimit (datën e temës) në të gjitha tryezat: tema, pjesëmarrësi.

Por tani kemi shfaqur menjëherë dy probleme:

  • nĂ« cilin seksion tĂ« kĂ«rkojmĂ« mesazhet sipas temĂ«s?
  • nĂ« cilin seksion tĂ« kĂ«rkojmĂ« temĂ«n nga mesazhi?

Mund ta vazhdojmë të kërkojmë në të gjitha seksionet, por kjo do të ishte shumë e trishtueshme dhe do të anulonte të gjitha përfitimet tona. Prandaj, për të ditur se ku saktësisht të kërkojmë, do të bëjmë lidhje logjike/indikatore për seksionet:

  • nĂ« mesazh do tĂ« shtojmĂ« njĂ« fushĂ« me datĂ«n e temĂ«s
  • temĂ«s do t'i shtojmĂ« njĂ« set datash tĂ« mesazheve tĂ« kĂ«tij bisedimi (mund tĂ« jetĂ« njĂ« tryezĂ« e veçantĂ«, ose njĂ« masĂ« e datave)

Baza e të dhënave të mesazheve (përgj.2): seksionojmë «në kohë reale»

Duke qenë se modifikimet e listës së datave të mesazheve për çdo bisedë do të jenë të pakta (sepse shumica e mesazheve bien në 1-2 ditët përkatëse), unë do të ndalëm pikërisht në një variant të tillë.

Pra, struktura e bazës sonë mori pamjen e mëposhtme me marrë parasysh sekcionimin:

Tabelat: RU, nëse keni një reagim të keq ndaj cirilikës në emrat e tabelave/fushave, është më mirë të mos shikoni

-- seksionet sipas datës së mesazhit
CREATE TABLE "Mesazhi_YYYYMMDD"(
  "Mesazhi"
    uuid
      PRIMARY KEY
, "Tema"
    uuid
, "DataTema"
    date
, "Autori"
    uuid
, "DataKoha" -- përdorim si datë
    timestamp
, "Teksti"
    text
);

CREATE TABLE "Adresati_YYYYMMDD"(
  "DataMesazhit"
    date
, "Mesazhi"
    uuid
, "Personi"
    uuid
, PRIMARY KEY("Mesazhi", "Personi")
);

CREATE TABLE "Skedari_YYYYMMDD"(
  "DataMesazhit"
    date
, "Skedari"
    uuid
      PRIMARY KEY
, "Mesazhi"
    uuid
, "BLOB"
    uuid
, "Emri"
    text
);

CREATE TABLE "RegjistriMesazheve_YYYYMMDD"(
  "DataMesazhit"
    date
, "Pronari"
    uuid
, "TipiRegjistrit"
    smallint
, "DataKoha"
    timestamp
, "Mesazhi"
    uuid
, PRIMARY KEY("Pronari", "TipiRegjistrit", "Mesazhi")
);
CREATE INDEX ON "RegjistriMesazheve_YYYYMMDD"("Pronari", "TipiRegjistrit", "DataKoha" DESC);

-- seksionet sipas datës së temës
CREATE TABLE "Tema_YYYYMMDD"(
  "DataTema"
    date
, "Tema"
    uuid
      PRIMARY KEY
, "Dokumenti"
    uuid
, "Emri"
    text
);

CREATE TABLE "PjesëmarrësiTemës_YYYYMMDD"(
  "DataTema"
    date
, "Tema"
    uuid
, "Personi"
    uuid
, PRIMARY KEY("Tema", "Personi")
);

CREATE TABLE "DatatMesazheveTemës_YYYYMMDD"(
  "DataTema"
    date
, "Tema"
    uuid
      PRIMARY KEY
, "Data"
    date
);

Kënësojme pak

Por, nĂ«se nuk pĂ«rdorim varianti klasik i sekcionimit nĂ« bazĂ« tĂ« shpĂ«rndarjes sĂ« vlerave tĂ« fushĂ«s (nĂ«pĂ«rmjet triggers dhe trashĂ«gimisĂ« ose PARTITION BY), por “duke e bĂ«rĂ«â€ manualisht nĂ« nivelin e aplikacionit, mund tĂ« vĂ«rejmĂ« se vlera e çelĂ«sit tĂ« sekcionimit tashmĂ« ruhet nĂ« emrin e vetĂ« tabelĂ«s.

Prandaj, nĂ«se shqetĂ«soheni aq shumĂ« pĂ«r volumet e tĂ« dhĂ«nave tĂ« ruajtura, atĂ«herĂ« mund tĂ« heqim kĂ«to “tĂ« tepĂ«rta” fusha dhe tĂ« drejtohemi direkt nĂ« tabelat specifike. MegjithatĂ«, tĂ« gjitha zgjedhjet nga disa seksione nĂ« kĂ«tĂ« rast do tĂ« duhet tĂ« kalohen nĂ« anĂ«n e aplikacionit.

Burimi: habr.com

Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS đŸ”„ Bleni hostim tĂ« besueshĂ«m pĂ«r faqe me mbrojtje nga DDoS, serverĂ« VPS VDS | ProHoster