data

Columnar storage: când Postgres nu mai e suficient pentru analize

Columnar storage stochează fiecare coloană separat pe disc. Rezultat: query-uri analitice de 10-100x mai rapide față de un Postgres row-based la volum mare.

Cuprins

Columnar storage este o metodă de organizare a datelor pe disc în care fiecare coloană a unui tabel este stocată consecutiv, separat de celelalte coloane. Diferit de bazele de date relaționale clasice, care stochează fiecare rând în întregime pe disc, columnar storage permite unui query analitic să citească doar coloanele de care are nevoie, sărind complet restul datelor.

Diferența produce rezultate dramatic diferite pentru workload-uri analitice. Un SUM(price) GROUP BY category pe 100 de milioane de rânduri citește două coloane în loc de tot rândul, comprimă datele similare împreună și finalizează în secunde acolo unde un Postgres row-based ar dura minute.

Ce înseamnă columnar storage mai exact?

Într-o bază de date row-based (Postgres, MySQL), un tabel cu coloanele produs, categorie, pret, data stochează pe disc fiecare rând complet. Un query care citește doar pret și categorie trebuie să parcurgă toți câmpii fiecărui rând.

În columnar storage, toate valorile pentru pret sunt stocate împreună, toate valorile pentru categorie sunt stocate împreună, separat. Același query citește exact două benzi de date de pe disc, indiferent câte coloane are tabelul. Avantajele structurale sunt două:

  • I/O redus. La un tabel cu 50 de coloane, un query pe 2 coloane citește 4% din date față de 100% în row-based. La volume mari, diferența de performanță este de un ordin de mărime sau mai mult.
  • Compresie mai bună. Valorile similare sunt adiacente pe disc (toate prețurile la un loc, toate categoriile la un loc). Algoritmii de compresie funcționează mult mai eficient pe date omogene. Un fișier Parquet cu date financiare se comprimă frecvent la 10-20% din dimensiunea CSV-ului echivalent.

Columnar storage este o proprietate a modului de stocare, nu un produs specific. O regăsești în formate de fișier (Parquet, ORC), în motoare de baze de date (ClickHouse, Redshift, BigQuery) și în biblioteci de analiză in-process (DuckDB, Apache Arrow).

De ce e mai rapid pentru workload-uri analitice?

Viteza vine din modul în care query-urile analitice consumă datele. Un query de tip SUM, AVG, GROUP BY operează pe coloane întregi, nu pe rânduri individuale. Trei mecanisme concrete contribuie la diferența de performanță:

  • Predicate pushdown. Parquet stochează statistici (min, max, count) per bloc de rânduri; un query cu WHERE data > '2026-01-01' sare blocurile irelevante fără să le citească.
  • Vectorizare SIMD. Operațiile pe coloane omogene se mapează pe instrucțiunile SIMD ale procesorului modern, care procesează sute de valori pe ciclu de ceas. DuckDB și ClickHouse exploatează agresiv această paralelizare.
  • Compresie mai bună. Dictionary encoding permite calcularea GROUP BY category direct pe coduri întregi în loc de șiruri de caractere. Memoria și banda de I/O scad proporțional.

Revers al avantajelor: aceleași caracteristici fac columnar storage prost pentru tranzacții OLTP. Un INSERT care adaugă un singur rând trebuie să actualizeze fiecare fișier de coloană în parte. Motoarele columnar sunt construite pentru batch append, nu pentru scrieri individuale frecvente. Detaliile despre separarea workload-urilor OLAP față de OLTP sunt în intrarea dedicată.

Care sunt opțiunile principale (Parquet, ClickHouse, DuckDB, BigQuery)?

Ecosistemul columnar s-a fragmentat în mai multe direcții, fiecare cu un compromis diferit:

  • Parquet. Format de fișier open-source (Apache), citit de aproape orice motor analitic: Spark, DuckDB, Polars, Athena, BigQuery. Stochezi columnar pe disc sau în object storage; ai nevoie de un motor separat pentru query-uri. Portabilitate maximă, fără legare de vendor.
  • ClickHouse. Motor de baze de date columnar open-source cu SQL complet. Conceput pentru volume mari și latențe mici pe analize în timp real. Scrierile se fac în batch-uri; insert single-row este lent prin design. Potrivit când ai milioane de evenimente pe zi și vrei query-uri sub secundă pe tot istoricul.
  • DuckDB. Motor in-process, fără server, rulează ca bibliotecă în Python, R sau Java. Citește direct Parquet, CSV, Postgres și alte surse. Ideal pentru analize locale sau pipeline-uri de transformare. Nu este potrivit pentru accese concurente de la mai mulți utilizatori simultan.
  • BigQuery și Amazon Redshift. Variante managed în cloud. BigQuery facturează per TB scanat (avantajos pentru workload-uri neregulate), Redshift per nod activ (avantajos pentru volume predictibile). Fără overhead de operare, cu dependență de vendor.
  • Apache Iceberg și Delta Lake. Formate de tip table format peste Parquet, adăugând tranzacționalitate ACID, schema evolution și time travel pe object storage. Baza arhitecturii lakehouse, discutate în detaliu în intrarea despre data warehouse.

Cum decidem când migrăm de la Postgres la columnar?

Decizia de migrare ar trebui să fie un semnal din monitorizare, nu o estimare preventivă. Semnalele concrete care justifică tranziția apar de obicei în această ordine:

  • Query-urile analitice afectează latența operațională. Dacă un raport crește timpii de răspuns pe endpoint-urile din aplicație, ai un conflict real de workload. Acesta este primul semnal serios că separarea fizică este necesară.
  • Optimizarea query-urilor analitice devine o activitate repetitivă. Dacă echipa petrece timp semnificativ refactorizând rapoarte ca să nu blocheze operaționalul, arhitectura a depășit capacitatea actuală a Postgres-ului.
  • Fereastra de scan pe Postgres depășește praguri acceptabile. Query-uri analitice care durează zeci de secunde sau minute, chiar și cu view-uri materializate, indică un volum care a depășit ce poate servi rezonabil un motor row-based.
  • Costul stocării Postgres devine comparabil cu un warehouse cloud. La sute de GB sau câțiva TB, costul unui Redshift sau BigQuery devine competitiv față de un VPS cu stocare SSD dedicată.

Pe RestoInsights, la peste 24 de milioane de înregistrări reîmprospătate nocturn1, Postgres cu materializare disciplinată acoperă nevoile analitice curente. Stack-ul de observabilitate va semnala când a sosit momentul unui strat columnar separat. Procesul de ingestie care ar alimenta acel strat este tipul de flux descris în intrarea despre ETL vs ELT.

Care sunt capcanele migrării (cost, complexitate, scrieri lente)?

Migrarea la columnar storage aduce un set de surprize pentru echipele obișnuite cu Postgres. Cele mai frecvente:

  • Scrierile sunt lent prin design. Columnar storage nu este un Postgres mai rapid; este un sistem optimizat diferit. Dacă aplicația ta face INSERT individual la fiecare eveniment, un motor columnar nu o să ajute, o să agraveze. Ingestia în motoare columnar se face în batch-uri (mii sau sute de mii de rânduri odată), sincronizate de obicei nocturn sau orar via n8n sau un orchestrator dedicat.
  • Nu există un buton de migrare. Nu poți „schimba" Postgres la columnar. Ai nevoie de un pipeline ETL sau ELT care extrage datele din sursa operațională, le transformă în schema analitică și le încarcă periodic în sistemul columnar. Acesta este un proiect de inginerie separat, nu o configurare.
  • Managementul schemei devine mai complex. Fără un instrument de versionare a schemei echivalent cu Liquibase, modificările de schemă în motoare columnar (ClickHouse, BigQuery) se fac ad-hoc. Schema drift și tabele orfane apar rapid fără disciplină explicită de data governance.
  • Costurile cloud pot surprinde. BigQuery facturează per TB scanat: un SELECT * neintenționat pe un tabel mare generează o factură semnificativă. Fără partitionare obligatorie și limite pe utilizatori, costurile explodează înainte să remarci.
  • Operarea self-hosted (ClickHouse) are overhead real. Un cluster ClickHouse self-hosted necesită administrare similară cu Postgres, dar cu mai puține cunoștințe disponibile în echipele mici. ClickHouse Cloud sau BigQuery elimină overhead-ul, dar adaugă dependența de vendor și costuri variabile.

Capcana frecventă este să decizi migrarea pe baza volumului, nu pe baza unui semnal real din monitorizare. Un Postgres cu view-uri materializate și separare disciplinată a workload-urilor, descrisă în OLAP vs OLTP, amână nevoia de columnar storage cu luni sau ani.

  1. RestoInsights gestionează peste 24 de milioane de înregistrări, reîmprospătate noapte de noapte, într-un singur Postgres cu materializare disciplinată. [resto.records_count]

Întrebări frecvente

Columnar storage înlocuiește Postgres?

Nu, le rezolvă probleme diferite. Postgres excelează la tranzacții frecvente și scurte (INSERT, UPDATE, lookup după cheie). Columnar storage excelează la query-uri analitice care scanează coloane întregi pe sute de milioane de rânduri. Majoritatea echipelor au nevoie de amândouă: Postgres pentru operațional, un motor columnar pentru analitice.

Parquet vs ClickHouse vs DuckDB: care aleg?

Depinde de ce vrei să faci cu datele. Parquet este un format de fișier, nu un motor: stochezi datele columnar pe disc (S3, local), le interoghezi cu DuckDB, Spark sau Polars. ClickHouse este un motor de bază de date columnar cu SQL complet, ideal pentru volume mari și latențe mici. DuckDB este un motor in-process fără server, potrivit pentru analize locale sau în pipeline-uri mici. BigQuery și Redshift sunt variante managed în cloud.

De ce scrierile sunt lente în columnar storage?

Pentru că inserarea unui singur rând înseamnă actualizarea fiecărui fișier de coloană în parte. La Postgres, un INSERT adaugă rândul într-o singură pagină. La ClickHouse sau Parquet, fiecare coloană este stocată separat; un rând nou modifică toate fișierele de coloană simultan. Motoarele columnar sunt optimizate pentru batch append (mii sau milioane de rânduri odată), nu pentru insert single-row continuu.

Pot folosi DuckDB fără să schimb Postgres?

Da, DuckDB poate citi direct din Postgres sau din fișiere Parquet fără să migrezi date. Rulezi DuckDB ca un layer de interogare analitică peste datele existente: conectezi la Postgres via extensia postgres_scanner, sau exporți periodic în Parquet și interoghezi local. Zero schimbări la aplicația operațională.

La câte rânduri are sens columnar storage?

Semnalul real nu este numărul de rânduri, ci dacă query-urile analitice afectează latența operațională. Unele echipe migrează la câteva milioane de rânduri; altele rulează zeci de milioane fără probleme în Postgres cu materializare. Pragul de migrare este un semnal din monitorizare, nu o regulă universală de volum.