Database di Messenger (Part 2): partitioning "per prufittu"

Avemu cuncepitu cù successu a struttura di a nostra basa di dati PostgreSQL per almacenà a currispundenza, un annu hè passatu, l'utilizatori l'anu attivamente riempitu, è avà cuntene milioni di dischi, è... qualcosa hà cuminciatu à rallentà.

Database di Messenger (Part 2): partitioning "per prufittu"
Point hè chì Cume a dimensione di a tavula cresce, ancu a "prufundità" di l'indici. - seppuru logaritmicu. Ma cù u tempu, questu forza u servitore à fà e stesse attività di lettura / scrittura processà parechje volte più pagine di datichè à u principiu.

Questu hè induve vene à u salvamentu seccionamentu.

Lasciami nutà chì ùn parlemu micca di sharding, vale à dì, di distribuzione di dati trà e diverse basa di dati o servitori. Perchè ancu dividendu i dati in parechji servitori, ùn avete micca sbarazzatu di u prublema di l'indici "swelling" cù u tempu. Hè chjaru chì se pudete permette di mette in opera un novu servitore ogni ghjornu, i vostri prublemi ùn si trovanu più in u pianu di una basa di dati specifica.

Avemu da cunsiderà micca scripts specifichi per implementà a partizione "in hardware", ma l'approcciu stessu - ciò chì è cumu deve esse "tagliatu in fette", è ciò chì un tali desideriu porta.

Cuncepimentu

Definimu di novu u nostru scopu: vulemu assicurà chì oghje, dumane, è in un annu, a quantità di dati letti da PostgreSQL durante ogni operazione di lettura / scrittura ferma apprussimatamente a stessa.

Per ogni dati accumulati cronologicamente (missaghji, documenti, logs, archivi, ...) a scelta naturale cum'è una chjave di particione hè data / ora di l'avvenimentu. In u nostru casu, un tali avvenimentu hè mumentu di mandà u missaghju.

Nota chì l'utilizatori quasi sempre travaglià solu cù l'"ultimi". tali dati - leghjenu l'ultime messagi, analizà l'ultimi logs, ... No, sicuru, ponu scorri più in u tempu, ma facenu questu assai raramenti.

Da queste limitazioni hè chjaru chì a suluzione ottimali di missaghju seria sezioni "quotidiana". - dopu tuttu, u nostru utilizatore hà da leghje guasi sempre ciò chì hè vinutu à ellu "oghje" o "ieri".

Sè avemu scrivite è leghje quasi solu in una sezione durante u ghjornu, allora questu ci dà ancu usu più efficaci di a memoria è u discu - postu chì tutti l'indici di sezione si adattanu facilmente in a RAM, in cuntrastu cù i "grandi è grassi" in tutta a tavula.

passu à passu

In generale, tuttu ciò chì dice sopra sona cum'è un prufittu cuntinuu. È hè pussibule, ma per questu avemu da pruvà dura - perchè a decisione di spartizione una di l'entità porta à a necessità di "visti" l'associati.

Missaghju, e so proprietà è prughjezzione

Siccomu avemu decisu di taglià i missaghji per date, hè sensu di dividisce ancu l'entità-proprietà chì dependenu di elli (fichi attacheti, lista di destinatari), è ancu per data di u messagiu.

Siccomu unu di i nostri compiti tipici hè precisamente a visualizazione di i registri di missaghju (unread, incoming, all), hè ancu logicu di "disegnali in" in partizioni per date di messagiu.

Database di Messenger (Part 2): partitioning "per prufittu"

Aghjunghjemu a chjave di particione (data di u missaghju) à tutti i tavulini: destinatari, file, registri. Ùn avete micca aghjunghje à u missaghju stessu, ma aduprà u DateTime esistenti.

Temi

Siccomu ci hè solu un tema per parechji missaghji, ùn ci hè micca manera di "tagliallu" in u stessu mudellu; duvete cunfidà di qualcosa altru. In u nostru casu hè ideale data di u primu messagiu in currispundenza - vale à dì, u mumentu di a creazione, in fatti, di u tema.

Database di Messenger (Part 2): partitioning "per prufittu"

Aghjunghjite a chjave di partizione (data di u tema) à tutte e tavule: tema, participante.

Ma avà avemu dui prublemi à una volta:

  • In quale rùbbrica deve circà i missaghji nantu à u tema ?
  • In quale rùbbrica deve cercà u tema da u missaghju?

Pudemu, sicuru, cuntinuà a ricerca in tutte e rùbbriche, ma questu serà assai tristu è negarà tutte e nostre vincite. Dunque, per sapè induve esattamente circà, faremu ligami lògichi / puntatori à e rùbbriche:

  • avemu da aghjunghje in u missaghju campu di data di u tema
  • aghjunghje à u tema data di u messagiu stabilitu sta currispundenza (pò esse una tavula separata, o una serie di date)

Database di Messenger (Part 2): partitioning "per prufittu"

Siccomu ci saranu pocu mudificazioni à a lista di e date di u messagiu per ogni currispundenza individuale (dopu à tuttu, quasi tutti i messagi cascanu nantu à 1-2 ghjorni adiacenti), mi fucalizza nantu à questa opzione.

In tuttu, a struttura di a nostra basa di dati hà pigliatu a forma seguente, tenendu in contu a particione:

Tables: RU, sè vo avete una aversione à l'alfabetu cirillicu in i nomi di tavule / campi, hè megliu micca di circà

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

Risparmiate un bellu centesimu

Ebbè, chì si usamu micca opzione di seccionamentu classicu basatu annantu à a distribuzione di i valori di u campu (attraversu triggers è eredità o PARTITION BY), è "manualmente" à u livellu di l'applicazione, vi vede chì u valore di a chjave di partizionamentu hè digià almacenatu in u nome di a tavola stessa.

Allora sì sì cusì Sò assai preoccupatu per a quantità di dati almacenati?, tandu pudete sbarazzà di sti campi "extra" è indirizzà tavule specifiche. True, tutte e selezzione da parechje rùbbriche in questu casu anu da esse trasferitu à u latu di l'applicazione.

Source: www.habr.com

Add a comment