Partiționarea Declarativă a Tabelelor în PostgreSQL (PARTITION BY) în PostgreSQL

Ghid complet pentru partiționarea nativă a tabelelor mari în PostgreSQL: partiționare după intervale (RANGE), liste (LIST) și hash, mecanismul de Partition Pruning și detașarea fără blocaj.

Sintaxă SQL
CREATE TABLE loguri (...) PARTITION BY RANGE (created_at); CREATE TABLE loguri_2026_q1 PARTITION OF loguri ...

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.

Crearea unei tabele partiționate după dată (RANGE)
-- 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ă!