Messengeri andmebaas (2. osa): partitsioonid "kasumi eesmärgil"

Oleme edukalt kujundanud oma PostgreSQL-i andmebaasi struktuuri kirjavahetuse salvestamiseks, aasta on möödas, kasutajad täidavad seda aktiivselt ja nüüd sisaldab see miljoneid rekordeid, ja... midagi hakkas aeglustuma.

Messengeri andmebaas (2. osa): partitsioonid "kasumi eesmärgil"
Fakt on see, et Tabeli suuruse kasvades kasvab ka indeksite “sügavus”. - kuigi logaritmiliselt. Kuid aja jooksul sunnib see serverit täitma samu lugemis-/kirjutusülesandeid töödelda mitu korda rohkem lehekülgi andmeidkui alguses.

Siin tulebki appi sektsioonide lõikamine.

Märgin ära, et me ei räägi shardingist ehk andmete jagamisest erinevate andmebaaside või serverite vahel. Sest isegi andmete jagamine mõned serverites, ei vabane te aja jooksul indeksite "paisumise" probleemist. Selge on see, et kui saad endale lubada iga päev uue serveri tööle panemist, siis sinu probleemid ei peitu enam üldsegi konkreetse andmebaasi tasandil.

Vaatleme mitte konkreetseid skripte partitsioonide rakendamiseks "riistvaras", vaid lähenemist ennast - mida ja kuidas tuleks "viiludeks lõigata" ning milleni selline soov viib.

Kontseptsioon

Määratleme oma eesmärgi veel kord: tahame olla kindlad, et täna, homme ja aasta pärast jääb PostgreSQL-i lugemis-/kirjutustoimingu ajal loetud andmete hulk ligikaudu samaks.

Iga kronoloogiliselt kogutud andmed (sõnumid, dokumendid, logid, arhiivid, ...) on loomulik valik partitsioonivõtmeks sündmuse kuupäev/kellaaeg. Meie puhul selline sündmus on sõnumi saatmise hetk.

Pange tähele, et kasutajad peaaegu alati töötage ainult "viimastega". sellised andmed - nad loevad viimaseid sõnumeid, analüüsivad viimaseid logisid... Ei, muidugi, nad võivad ajas kaugemale kerida, kuid nad teevad seda väga harva.

Nende piirangute põhjal on selge, et optimaalne sõnumilahendus oleks "igapäevased" jaotised - lõppude lõpuks loeb meie kasutaja peaaegu alati seda, mis talle “täna” või “eile” jõudis.

Kui me kirjutame ja loeme päeva jooksul peaaegu ainult ühes osas, siis see annab meile ka mälu ja ketta tõhusam kasutamine - kuna kõik jaotise indeksid mahuvad hõlpsasti RAM-i, erinevalt kogu tabeli "suurtest ja paksudest".

samm sammu haaval

Üldiselt kõlab kõik ülalöeldu nagu üks pidev kasum. Ja see on saavutatav, kuid selleks peame kõvasti pingutama - sest otsus üks olem osadeks jaotada toob kaasa vajaduse seostatud "nägida"..

Sõnum, selle omadused ja projektsioonid

Kuna otsustasime kirju lõigata kuupäevade järgi, on mõttekas jagada ka neist sõltuvad olemid-atribuudid (manustatud failid, saajate loend) ja ka sõnumi kuupäeva järgi.

Kuna üks meie tüüpilisi ülesandeid on just sõnumiregistrite (lugemata, sissetulevad, kõik) vaatamine, on loogiline ka need sõnumikuupäevade järgi partitsioonidesse “joonistada”.

Messengeri andmebaas (2. osa): partitsioonid "kasumi eesmärgil"

Lisame partitsioonivõtme (sõnumi kuupäeva) kõikidesse tabelitesse: saajad, fail, registrid. Te ei pea seda lisama sõnumile endale, vaid kasutage olemasolevat DateTime.

Teemad

Kuna mitme sõnumi jaoks on ainult üks teema, siis ei saa seda samasse mudelisse “lõigata”, vaid tuleb loota millelegi muule. Meie puhul on see ideaalne esimese kirjavahetuse kuupäev — ehk siis tegelikult teema loomise hetk.

Messengeri andmebaas (2. osa): partitsioonid "kasumi eesmärgil"

Lisa partitsioonivõti (teema kuupäev) kõikidele tabelitele: teema, osaleja.

Kuid nüüd on meil kaks probleemi korraga:

  • Millisest rubriigist peaksin otsima selleteemalisi sõnumeid?
  • Millisest rubriigist peaksin sõnumist teemat otsima?

Muidugi võime jätkata otsimist kõigis jaotistes, kuid see on väga kurb ja muudab kõik meie võidud olematuks. Seetõttu, et teada saada, kust täpselt otsida, teeme jaotistele loogilised lingid/viited:

  • lisame sõnumisse teema kuupäeva väli
  • lisame teemasse sõnumi kuupäev määratud see kirjavahetus (võib olla eraldi tabel või kuupäevade massiiv)

Messengeri andmebaas (2. osa): partitsioonid "kasumi eesmärgil"

Kuna iga üksiku kirjavahetuse sõnumikuupäevade loendis tehakse vähe muudatusi (peaaegu kõik sõnumid langevad ju 1-2 külgnevale päevale), keskendun sellele valikule.

Kokkuvõttes oli meie andmebaasi struktuur järgmine, võttes arvesse partitsiooni:

Tabelid: RU, kui teil on tabelite/väljade nimedes vastumeelsus kirillitsa tähestiku vastu, siis on parem mitte vaadata

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

Säästa ilus senti

Noh, mis siis, kui me ei kasuta klassikaline jaotusvõimalus välja väärtuste jaotuse põhjal (käivitajate ja pärimise või PARTITION BY kaudu) ja rakenduse tasemel "käsitsi" märkate, et partitsioonivõtme väärtus on juba tabeli enda nimes salvestatud.

Nii et kui sa oled nii Kas olete salvestatud andmete hulga pärast väga mures?, siis saate nendest “lisa” väljadest lahti saada ja konkreetseid tabeleid käsitleda. Tõsi, kõik valikud mitmest jaotisest tuleb sel juhul üle kanda rakenduse poolele.

Allikas: www.habr.com

Lisa kommentaar