Când o tabelă depășește zeci sau sute de milioane de rânduri, indecșii B-Tree devin prea mari pentru a încăpea în memoria RAM (shared_buffers), iar operațiunile de VACUUM și scanare devin extrem de lente. Partiționarea Declarativă (introdusă în PostgreSQL 10 și maturizată complet în versiunile 14-17) permite împărțirea logică a unui tabel masiv în tabele fizice mai mici, complet transparente pentru aplicație.
-- 1. Creăm tabela părinte declarativă (nu conține date fizice)
CREATE TABLE tranzactii (
id BIGINT GENERATED ALWAYS AS IDENTITY,
client_id INT NOT NULL,
suma NUMERIC(12, 2) NOT NULL,
created_at TIMESTAMPTZ NOT NULL,
PRIMARY KEY (id, created_at) -- Coloana de partiționare trebuie inclusă în cheia primară!
) PARTITION BY RANGE (created_at);
-- 2. Creăm partițiile fizice pentru fiecare trimestru
CREATE TABLE tranzactii_2026_t1 PARTITION OF tranzactii
FOR VALUES FROM ('2026-01-01 00:00:00+00') TO ('2026-04-01 00:00:00+00');
CREATE TABLE tranzactii_2026_t2 PARTITION OF tranzactii
FOR VALUES FROM ('2026-04-01 00:00:00+00') TO ('2026-07-01 00:00:00+00');
-- 3. Inserăm date în tabela părinte; PostgreSQL le rutează automat în partiția corectă!
INSERT INTO tranzactii (client_id, suma, created_at)
VALUES (15, 349.99, '2026-02-15 10:30:00+02');
Strategii de Partiționare Declarativă
| Strategie | Sintaxă de Bază | Caz de Utilizare Tipic |
|---|---|---|
| PARTITION BY RANGE | FOR VALUES FROM (x) TO (y) |
Serii de timp, loguri de server, date calendaristice, tranzacții financiare trimestriale/lunare. |
| PARTITION BY LIST | FOR VALUES IN ('RO', 'DE', 'FR') |
Partiționare regională (pe țări sau regiuni geografice) sau după statusul comenzilor. |
| PARTITION BY HASH | WITH (MODULUS 4, REMAINDER 0) |
Distribuirea uniformă a rândurilor pe un număr fix de partiții pentru a paraleliza scrierile. |
Magia Performanței: Partition Pruning
Dacă emiteți o interogare cu filtru pe coloana de partiționare, optimizatorul PostgreSQL elimină automat din planul de execuție partițiile care nu pot conține date relevante:
EXPLAIN SELECT * FROM tranzactii WHERE created_at >= '2026-05-01';
În planul de execuție veți observa că tranzactii_2026_t1 nu este nici măcar atinsă! PostgreSQL scanează exclusiv tranzactii_2026_t2, reducând I/O-ul proporțional cu numărul de partiții eliminate.
Mentenanță Zero-Downtime: Detașarea Datelor Vechi
În loc să rulați un DELETE FROM tranzactii WHERE created_at < '2024-01-01' (care ar genera milioane de dead tuples și ar bloca baza de date), în PostgreSQL puteți pur și simplu detașa partiția veche instantaneu:
-- Detașăm partiția fără a bloca interogările concurente:
ALTER TABLE tranzactii DETACH PARTITION tranzactii_2024_t1 CONCURRENTLY;
-- Acum tabela detașată poate fi arhivată pe S3 sau ștearsă instantaneu cu DROP TABLE:
DROP TABLE tranzactii_2024_t1; -- Durează sub 1 milisecundă!