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 milioni zapisa, i ... nešto je počelo sve usporavati.

Messenger baza podataka (2. dio): particioniranje "za profit"
Stvar je u tome sa rastom obima tabele, raste i „dubina“ indeksa - iako logaritamski. Ali s vremenom to prisiljava server da radi iste zadatke čitanja/pisanja obrađuju mnogo puta više stranica sa podacimanego na početku.

Tu dolazi do spašavanja sekcija.

Napominjem da se ne radi o shardingu, odnosno distribuciji podataka između različitih baza podataka ili servera. Jer čak i dijeljenje podataka sa nekoliko servera, nećete se riješiti problema "nabujanja" indeksa tokom vremena. Jasno je da ako si možete priuštiti stavljanje novog servera u rad svaki dan, onda vaši problemi više neće ležati na nivou određene baze podataka.

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

Koncept

Još jednom definišemo naš cilj: želimo da budemo sigurni da danas, sutra i godinu dana kasnije, količina podataka koje PostgreSQL čita za bilo koju operaciju čitanja/pisanja ostaje približno ista.

Za bilo koje hronološki akumulirani podaci (poruke, dokumenti, evidencije, arhive,...) prirodan izbor za particioni ključ je datum/vrijeme događaja. U našem slučaju, ovaj događaj jeste u trenutku kada je poruka poslata.

Imajte na umu da korisnici gotovo uvijek raditi samo sa najnovijim takvi podaci - čitaju najnovije poruke, analiziraju najnovije logove,... Ne, naravno, mogu se pomicati i dalje u prošlost, samo što to rade vrlo rijetko.

Iz ovih ograničenja postaje očigledno da će optimalno rješenje za poruke biti "dnevne" sekcije - uostalom, gotovo uvijek će naš korisnik pročitati ono što mu je stiglo "danas" ili "juče".

Ako u toku dana pišemo i čitamo praktično samo u jednom dijelu, onda nam i to daje efikasnije korištenje memorije i diska - pošto se svi indeksi sekcija lako uklapaju u RAM, za razliku od onih "velikih i debelih" u tabeli.

korak po korak

Generalno, sve navedeno zvuči kao jedan veliki profit. I to je ostvarivo, ali za to ćemo se morati potruditi – jer odluka o podjeli jednog od entiteta dovodi do potrebe da se "pile" i pridruže.

Poruka, njena svojstva i projekcije

Budući da smo odlučili da smanjimo poruke po datumima, razumno je podijeliti i svojstva entiteta koja zavise od njih (priložene datoteke, lista primatelja) i takođe po datumu posta.

Budući da je jedan od naših tipičnih zadataka samo pregledavanje registara poruka (nepročitane, dolazne, sve), logično je i da ih "uvučemo" u sekcije prema datumima poruke.

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

Dodamo ključ particije (datum poruke) u sve tabele: primaoce, fajl, registre. Ne možete dodati samoj poruci, već koristiti postojeći DateTime.

teme

S obzirom da je tema jedna za više poruka, neće se moći „prerezati“ u istom modelu, potrebno je osloniti se na nešto drugo. Savršeno za naš slučaj. datum prve poruke u prepisci - odnosno trenutak stvaranja, zapravo, teme.

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

Dodajte ključ particije (datum predmeta) svim tablicama: tema, član.

Ali sada imamo dva problema odjednom:

  • u kojem dijelu tražiti poruke na temu?
  • u kojem dijelu tražiti predmet poruke?

Možete, naravno, nastaviti da tražite u svim odjeljcima, ali to će biti jako tužno i poništit će sve naše dobitke. Stoga, da bismo znali gdje tačno tražiti, napravićemo logičke veze / pokazivače na sekcije:

  • dodati u poruku polje datuma teme
  • dodati temu datum poruke je postavljen ova korespondencija (možete koristiti zasebnu tabelu ili možete koristiti niz datuma)

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

Budući da će biti nekoliko izmjena na listi datuma poruka za svaku pojedinačnu korespondenciju (na kraju krajeva, skoro sve poruke padaju na 1-2 susedna dana), fokusiraću se na ovu opciju.

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

Tablice : RU

-- секции по дате сообщения
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štedi prilično peni

Pa, šta ako koristimo klasično sečenje. na osnovu distribucije vrijednosti polja (preko okidača i nasljeđivanja ili PARTITION BY), ali "ručno" na razini aplikacije, primijetit ćete da je vrijednost particionog ključa već pohranjena u nazivu same tablice.

Pa ako jesi veoma su zabrinuti zbog količine pohranjenih podataka, tada se možete riješiti ovih "dodatnih" polja i obratiti se posebno određenim tablicama. Istina, svi odabiri iz nekoliko odjeljaka u ovom slučaju već će se morati prenijeti na stranu aplikacije.

izvor: www.habr.com

Dodajte komentar