Vrei să scalezi o bază de date relațională - gen MySQL? Perfect. În cadrul acestui articol, vei afla cum poți să faci asta.
Problemă: Să spunem că aplicația ta lucrează cu o bază de date relațională și una din tabelele din baza ta de date a ajuns să fie foarte mare și ca rezultat, a început să afecteze interogările de căutare care nu mai sunt la fel de rapide ca în trecut. În plus, să spunem că ne dorim ca această tabelă să o împărțim pe diverse mașini, pentru a putea scala orizontal și pentru a putea reduce poate și timpul de căutare. Să spunem că avem și un ID - auto increment ca și coloană primară pentru această tabelă.
Posibilă soluție: O variantă de a rezolva problema expusă mai sus este să apelăm la ceea ce se cheamă: database sharding. Pare simplu și rapid. Dar haideți mai întâi să înțelegem ce este de fapt database sharding? Conceptual, ideea de sharding este de a distribui datele dintr-o tabelă pe mai multe mașini. De exemplu, dacă am 1 million de înregistrări în tabelă și 2 mașini disponibile, o idee ar fi să le distribui uniform, primele 500k înregistrări pe prima mașină și ultimile 500k înregistrări pe a 2-a mașină. În funcție de modul în care le distribui, database sharding poate să fie range-based (cazul expus anterior) sau hashkey-based. Un exemplu de hashkey-based sharding este atunci când folosim o funcție de hashing (gen modulo 2) pentru a distribui datele pe noduri. În cazul cu cele 1 million de înregistrări, am putea să împărțim toate ID-urile pare pe prima mașină și toate ID-urile impare pe cea dea 2-a mașină.
Range-based sau hashkey-based?: Clar prima variantă. Ce se întâmplă dacă adăugăm o nouă mașină? Cum rezolvăm situația în care vrem să facem join cu o altă tabelă? Cum poți interoga înregistrările de la 100k la 200k ordonate descrescător după data modificării lor?
După cum se poate observa, database sharding introduce o complexitate ridicată, motiv pentru care ar trebui să fie tratată ca și o ultimă soluție. Ce alte variante mai avem?
Varianta 1: Sparge tabela în 2 sau mai multe - scalare verticală
O primă idee ar fi să spargem tabela noastră în 2 sau mai multe tabele. Mai întâi putem să ne gândim să o spargem în 2. Conceptual, ideea ar fi să avem o tabelă care nu se modifică decât foarte rar și cealaltă tabelă să conțină coloanele care se modifică foarte des. De fiecare dată când facem update vom aveam un lock pe tabelă. Acum, lock-ul se va face doar pe una din cele 2 tabele, deci am reușit să îmbunătățim performanța considerabil.
Varianta 2: Arhivarea
Poate că aplicația noastră nu îți permite să șteargă înregistrări, dar ce ar fi dacă pe cele mai vechi de X zile le-am putea arhiva? Asta ar însemna de fapt să facem un proces care periodic ia datele mai vechi de X zile din tabela noastră și le salvează în altă tabelă. Arhivarea poate fi însoțită și de comprimare pe disk, pentru a reduce memoria folosită pentru stocarea datelor vechi. Un dezavantaj al procesului de arhivare este faptul că dacă vrem să avem și o funcție de căutare prin vechile înregistrări, aceasta va funcționa mult mai lent datorită timpului de dezarhivare.
Varianta 3: Arhitectură împărțită în mașini dedicate pentru citire și altele dedicate pentru scriere
De fiecare dată când aplicația va scrie, aceasta va scrie în master nodes, iar de fiecare dată când va citi, va citi din slave nodes. Va exista o sincronizare între nodurile master si cele slave, de la master la slave. Aproape toate bazele de date cunoscute au acest feature.
Varianta 4: Partiționarea tabelei
Datele din tabelă, vor fi partiționate după dată, putând să avem o partiție pentru fiecare lună, de exemplu. O partiție nouă ar putea însemna un nou fișier pe disc. O limitare față de database sharding bazat pe range ar fi faptul că toate partițiile ar fi pe aceeași mașină fizică.
Iată câteva metode prin care poți optimiza baza ta de date. Happy optimizing!