Messenger-databasis (Deel 2): ​​partisionering "vir wins"

Ons het die struktuur van ons PostgreSQL-databasis suksesvol ontwerp vir die stoor van korrespondensie, 'n jaar is verby, gebruikers vul dit aktief in, en nou miljoene rekords, en ... iets het alles begin vertraag.

Messenger-databasis (Deel 2): ​​partisionering "vir wins"
Feit is dat met die groei van die tabelvolume, groei die “diepte” van die indekse ook - al is dit logaritmies. Maar met verloop van tyd dwing dit die bediener om dieselfde lees-/skryftake te doen verwerk baie keer meer databladsyeas aan die begin.

Dit is waar dit tot die redding kom verdeling.

Ek let daarop dat dit nie gaan oor sharding nie, dit wil sê die verspreiding van data tussen verskillende databasisse of bedieners. Omdat selfs die data te deel deur sommige bedieners, sal jy nie ontslae raak van die probleem van "swel" indekse met verloop van tyd. Dit is duidelik dat as jy dit kan bekostig om elke dag 'n nuwe bediener in werking te stel, dan sal jou probleme nie meer op die vlak van 'n spesifieke databasis lê nie.

Ons sal nie spesifieke skrifte vir die implementering van partisionering "in hardeware" oorweeg nie, maar die benadering self - wat en hoe moet "in skywe gesny word", en waartoe so 'n begeerte lei.

Konsep

Weereens, ons definieer ons doelwit: ons wil seker maak dat vandag, môre en 'n jaar later, die hoeveelheid data wat deur PostgreSQL gelees word vir enige lees / skryf-bewerking ongeveer dieselfde bly.

Vir enige chronologies opgehoopte data (boodskappe, dokumente, logs, argiewe, ...) die natuurlike keuse vir 'n partisiesleutel is datum/tyd van die geleentheid. In ons geval is hierdie gebeurtenis die oomblik toe die boodskap gestuur is.

Let daarop dat gebruikers byna altyd werk net met die nuutste sulke data - hulle lees die nuutste boodskappe, ontleed die nuutste logs, ... Nee, natuurlik, hulle kan verder terug in tyd blaai, net hulle doen dit baie selde.

Uit hierdie beperkings word dit duidelik dat die optimale oplossing vir boodskappe sal wees "daaglikse" afdelings - ons gebruiker sal immers byna altyd lees wat "vandag" of "gister" na hom toe gekom het.

As ons gedurende die dag feitlik net in een afdeling skryf en lees, dan gee dit ons ook meer doeltreffende geheue en skyfgebruik - aangesien alle afdeling-indekse maklik in die RAM pas, in teenstelling met die "groot en vet" regdeur die tabel.

stap vir stap

Oor die algemeen klink al die bogenoemde na een groot wins. En dit is haalbaar, maar hiervoor sal ons hard moet werk – want die besluit om een ​​van die entiteite te verdeel lei tot die behoefte om te "saag" en geassosieer.

Boodskap, sy eienskappe en projeksies

Aangesien ons besluit het om boodskappe volgens datums te sny, is dit ook redelik om die entiteit-eienskappe afhanklik daarvan te verdeel (aangehegte lêers, lys van ontvangers), en ook volgens posdatum.

Aangesien een van ons tipiese take net is om die boodskapregisters te bekyk (ongelees, inkomende, alles), is dit ook logies om dit volgens boodskapdatums te "trek" in afdelings.

Messenger-databasis (Deel 2): ​​partisionering "vir wins"

Ons voeg die partisiesleutel (boodskapdatum) by alle tabelle: ontvangers, lêer, registers. Jy kan nie by die boodskap self voeg nie, maar die bestaande DatumTyd gebruik.

Onderwerpe

Aangesien die onderwerp een vir verskeie boodskappe is, sal dit nie moontlik wees om dit in dieselfde model te "sny" nie, jy moet op iets anders staatmaak. Perfek vir ons geval. datum van die eerste boodskap in die korrespondensie - dit wil sê, die oomblik van skepping, in werklikheid, van die onderwerp.

Messenger-databasis (Deel 2): ​​partisionering "vir wins"

Voeg 'n partisiesleutel (vakdatum) by alle tabelle: onderwerp, lid.

Maar nou het ons twee probleme tegelyk:

  • in watter afdeling om boodskappe oor die onderwerp te soek?
  • in watter afdeling om na die onderwerp van die boodskap te soek?

Jy kan natuurlik voortgaan om in alle afdelings te soek, maar dit sal baie hartseer wees en sal al ons wengeld ontken. Daarom, om te weet waar presies om te kyk, sal ons logiese skakels / verwysings na afdelings maak:

  • voeg by die boodskap onderwerp datum veld
  • by die onderwerp voeg boodskap datum vasgestel hierdie korrespondensie (jy kan 'n aparte tabel gebruik, of jy kan 'n verskeidenheid datums gebruik)

Messenger-databasis (Deel 2): ​​partisionering "vir wins"

Aangesien daar min wysigings aan die lys boodskapdatums vir elke individuele korrespondensie sal wees (byna alle boodskappe val immers op 1-2 aangrensende dae), sal ek op hierdie opsie fokus.

In totaal het die struktuur van ons databasis die volgende vorm aangeneem, met inagneming van partisionering:

Tabelle: 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
);

Spaar 'n mooi sent

Wel, wat as ons gebruik klassieke snit. gebaseer op die verspreiding van veldwaardes (deur snellers en oorerwing of PARTITION BY), maar "handmatig" op die toepassingsvlak, sal jy sien dat die waarde van die partisiesleutel reeds in die naam van die tabel self gestoor is.

So as jy so is is baie bekommerd oor die hoeveelheid data wat gestoor word, dan kan jy ontslae raak van hierdie "ekstra" velde en spesifiek aan spesifieke tabelle adresseer. Dit is waar dat alle keuses uit verskeie afdelings in hierdie geval reeds na die toepassingskant oorgedra moet word.

Bron: will.com

Voeg 'n opmerking