Messenger-database (del 2): ​​partisjonering "for profitt"

Vi har utviklet strukturen til vår PostgreSQL-database for lagring av korrespondanse, et år har gått, brukere fyller den aktivt, og nå inneholder den millioner av poster, og... noe begynte å avta.

Messenger-database (del 2): ​​partisjonering "for profitt"
Faktum er at Etter hvert som tabellstørrelsen vokser, øker også "dybden" på indeksene. - om enn logaritmisk. Men over tid tvinger dette serveren til å utføre de samme lese-/skriveoppgavene behandle mange ganger flere sider med dataenn i begynnelsen.

Det er her det kommer til unnsetning seksjonering.

La meg merke at vi ikke snakker om sharding, det vil si distribusjon av data mellom forskjellige databaser eller servere. Fordi selv dele dataene inn i noen servere, vil du ikke bli kvitt problemet med at indeksene "svulmer opp" over tid. Det er klart at hvis du har råd til å sette en ny server i drift hver dag, vil problemene dine ikke lenger ligge i planet til en bestemt database.

Vi vil ikke vurdere spesifikke skript for implementering av partisjonering "i maskinvare", men selve tilnærmingen - hva og hvordan bør "skjæres i skiver", og hva et slikt ønske fører til.

konsept

La oss definere målet vårt nok en gang: vi vil sørge for at i dag, i morgen og om et år forblir mengden data som leses av PostgreSQL under enhver lese-/skriveoperasjon omtrent den samme.

For enhver kronologisk akkumulerte data (meldinger, dokumenter, logger, arkiver, ...) det naturlige valget som partisjoneringsnøkkel er dato/klokkeslett for arrangementet. I vårt tilfelle er en slik hendelse øyeblikket da meldingen ble sendt.

Merk at brukere nesten alltid fungerer bare med de "nyeste". slike data - de leser de siste meldingene, analyserer de siste loggene,... Nei, de kan selvfølgelig rulle lenger tilbake i tid, men de gjør dette svært sjelden.

Fra disse begrensningene er det klart at den optimale meldingsløsningen ville være "daglige" seksjoner - Tross alt vil brukeren vår nesten alltid lese hva som kom til ham "i dag" eller "i går".

Skriver og leser vi nesten bare i ett avsnitt i løpet av dagen, så gir dette oss også mer effektiv bruk av minne og disk - siden alle seksjonsindekser lett passer inn i RAM, i motsetning til de "store og fete" i hele tabellen.

steg for steg

Generelt høres alt som er nevnt ovenfor ut som ett kontinuerlig overskudd. Og det er oppnåelig, men for dette må vi prøve hardt - fordi beslutningen om å dele opp en av enhetene fører til behovet for å "se" den tilknyttede.

Melding, dens egenskaper og projeksjoner

Siden vi bestemte oss for å kutte meldinger etter datoer, er det fornuftig å også dele enhetene-egenskapene som er avhengige av dem (vedlagte filer, liste over mottakere), og også etter meldingsdato.

Siden en av våre typiske oppgaver er nettopp å se meldingsregistre (ulest, innkommende, alle), er det også logisk å "trekke dem inn" i partisjonering etter meldingsdatoer.

Messenger-database (del 2): ​​partisjonering "for profitt"

Vi legger til partisjoneringsnøkkelen (meldingsdato) til alle tabeller: mottakere, fil, registre. Du trenger ikke å legge den til i selve meldingen, men bruk den eksisterende DateTime.

tråder

Siden det bare er ett emne for flere meldinger, er det ingen måte å "klippe" det i samme modell; du må stole på noe annet. I vårt tilfelle er det ideelt dato for første melding i korrespondanse — det vil si skapelsesøyeblikket, faktisk av emnet.

Messenger-database (del 2): ​​partisjonering "for profitt"

Legg til partisjoneringsnøkkelen (emnedato) til alle tabeller: emne, deltaker.

Men nå har vi to problemer samtidig:

  • I hvilken del skal jeg se etter meldinger om emnet?
  • I hvilken del skal jeg se etter emnet fra meldingen?

Vi kan selvfølgelig fortsette å søke i alle seksjoner, men dette vil være veldig trist og vil oppheve alle våre gevinster. Derfor, for å vite nøyaktig hvor vi skal se, vil vi lage logiske lenker/pekere til seksjoner:

  • vi legger til i meldingen feltet for emnedato
  • la oss legge til emnet meldingsdato satt denne korrespondansen (kan være en separat tabell eller en rekke datoer)

Messenger-database (del 2): ​​partisjonering "for profitt"

Siden det vil være få endringer i listen over meldingsdatoer for hver enkelt korrespondanse (tross alt faller nesten alle meldinger på 1-2 tilstøtende dager), vil jeg fokusere på dette alternativet.

Totalt tok strukturen til databasen vår følgende form, med hensyn til partisjonering:

Tabeller: RU, hvis du har en aversjon mot det kyrilliske alfabetet i navnene på tabeller/felter, er det bedre å ikke se

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

Spar en pen krone

Vel, hva om vi ikke bruker klassisk seksjoneringsalternativ basert på distribusjon av feltverdier (gjennom triggere og arv eller PARTITION BY), og "manuelt" på applikasjonsnivå, vil du legge merke til at verdien til partisjonsnøkkelen allerede er lagret i navnet på selve tabellen.

Så hvis du er det Er du veldig bekymret for mengden data som lagres?, så kan du bli kvitt disse "ekstra" feltene og adressere spesifikke tabeller. Det er sant at alle valg fra flere seksjoner i dette tilfellet må overføres til applikasjonssiden.

Kilde: www.habr.com

Legg til en kommentar