olivlawolivlaw

Din cărți

Lecția 25 · Într-un depozit columnar, structura de date e așezarea pe disc: partiția și ordinea decid câte blocuri nu trebuie citite.

Linus Torvalds · Mesaj pe lista de discuții git · 2006 · Mesaj pe lista de discuții git, 27 iunie 20062 minute de citit
„Programatorii slabi se îngrijorează de cod. Programatorii buni se îngrijorează de structurile de date și de relațiile dintre ele.”Linus Torvalds · Mesaj pe lista de discuții git · 2006 · Mesaj pe lista de discuții git, 27 iunie 2006

Nu optimiza interogarea; așază datele astfel încât interogarea să nu aibă ce citi.

Indexul B-tree e regele bazelor tranzacționale: găsește un rând în câțiva pași. Depozitele columnare merg pe alt principiu: nu caută un rând, sar peste blocuri. Fiecare bloc de coloană poartă un min și un max (zone map); dacă filtrul cere „luna martie” și blocul acoperă „iunie–iulie”, blocul nu se citește deloc. De aici două pârghii. Partiționarea — de regulă pe dată — elimină directoare întregi înainte să înceapă interogarea. Clusterizarea (sau cheia de sortare) grupează valorile apropiate în aceleași blocuri, ca zone map-urile să aibă ce sări; fără ea, fiecare bloc conține de toate și niciunul nu se poate sări. Regulile de proiectare urmează filtrele, nu sosirea datelor: partiționezi pe ce se filtrează în interogări, clusterizezi pe a doua coloană din WHERE. Prea multe partiții înseamnă fișiere mici și metadate mai scumpe decât datele; se compactează. Pentru egalitate pe coloane cu multe valori distincte, filtrele Bloom; pentru agregări repetate, vederi materializate; iar statisticile actualizate rămân condiția ca toate acestea să fie folosite. Torvalds vorbea despre cod, dar regula ține: nu optimiza interogarea; așază datele astfel încât interogarea să nu aibă ce citi.

Pasajul de până acum explică cum partiția și sortarea taie blocuri. Pasul următor e mai puțin evident: aceste două pârghii se plătesc la scriere, nu doar la citire. Când alegi partiția și cheia de sortare, decizi de fapt ordinea în care datele intră pe disc, pentru totdeauna. O tabelă de comenzi partiționată pe lună și sortată după client va fi rapidă pentru rapoartele lunare pe client, dar lentă pentru orice filtru pe produs. De aceea proiectarea se face invers: te uiți întâi la întrebările care se vor pune, abia apoi la cum arată datele. Un exemplu obișnuit: arhivezi facturile lunare, dar contabilii filtrează mereu după furnizor. Dacă sortarea e pe dată, fiecare furnizor e risipit prin toate blocurile. Schimbi cheia de sortare și aceeași interogare citește o fracțiune. Dar ce se întâmplă când datele sosesc neordonate, în flux continuu, și nu le poți sorta odată?

În flux, datele sosesc în ordinea sosirii, nu în ordinea filtrului. Fiecare fișier mic primește un interval larg de valori, deci zone map-urile nu mai pot sări nimic. Soluția nu e să sortezi la citire, ci la scriere, mai târziu: compactarea. Sistemul unește fișierele mici în fișiere mari, sortate, și rescrie statisticile. E ca și cum ai arunca poșta în vraf toată ziua, apoi ai sorta-o seara în dosare. Interogările care rulează între timp plătesc prețul vrafului, dar cele de după citesc dosare. Apare însă o întrebare: cât de des să compactezi și cât de mari să fie fișierele?

De ce contează Diferența dintre o interogare de trei secunde și una de trei minute pe aceleași date e, de obicei, doar ordinea în care au fost scrise pe disc.

Filtrul dininterogareEliminăpartițiileSareblocurileCiteștedoar ce
Performanța e ce nu citești.
Deschide pe YouTube ↗

← Vezi tot fluxul