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à.
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.
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.
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)
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.