Ce face CREATE INDEX (B-Tree, GIN, Partial, CONCURRENTLY)
PostgreSQL are unul dintre cele mai bogate sisteme de indexare din lumea bazelor de date. Pe lângă indexul implicit B-Tree (pentru egalități, intervale <, >, BETWEEN și sortări ORDER BY), oferă indecși GIN (Generalized Inverted Index — ideali pentru valori compuse precum JSONB, tablouri ARRAY și căutare full-text), GiST (date geometrice/intervale) și BRIN (tabele uriașe ordonate cronologic).
Mai mult, PostgreSQL suportă indecși parțiali (cu clauza WHERE, care indexează doar un subset de rânduri), indecși pe expresii (ex: LOWER(email)), indecși acoperitori (INCLUDE, pentru Index-Only Scans) și opțiunea CONCURRENTLY, care construiește indexul în producție fără a bloca operațiile INSERT, UPDATE și DELETE.
Clauze, operatori și argumente
| Clauză / Operator | Descriere |
|---|---|
USING btree (implicit) |
Index echilibrat standard pentru =, <, <=, >, >=, IN, IS NULL și ORDER BY. |
USING gin (coloana) |
Index inversat pentru coloane jsonb (operatorii @>, ?), tablouri ARRAY (@>, &&) și căutare full-text. |
CONCURRENTLY |
Construiește indexul fără a bloca scrierile pe tabel (nu poate fi rulat în interiorul unui bloc BEGIN ... COMMIT). |
WHERE conditie |
Creează un index parțial doar pentru rândurile care satisfac condiția, reducând masiv dimensiunea indexului. |
INCLUDE (col1, col2) |
Atașează coloane suplimentare în frunzele indexului B-Tree pentru a permite Index-Only Scan fără citirea tabelului. |
UNIQUE NULLS NOT DISTINCT |
În PostgreSQL 15+, tratează două valori NULL ca fiind egale într-un index unic. |
Exemple
Exemplul 1: Crearea unui index GIN pentru JSONB și a unui index pe expresie (LOWER)
Accelerăm căutările în documentele specificatii cu un index GIN (fără blocarea tabelului prin CONCURRENTLY) și căutările insensibile la majuscule pe email.
CREATE INDEX CONCURRENTLY idx_produse_specificatii_gin
ON produse USING gin (specificatii);
CREATE UNIQUE INDEX CONCURRENTLY idx_utilizatori_email_lower
ON utilizatori (LOWER(email));
Rezultat interogare
CREATE INDEX
CREATE INDEX
Exemplul 2: Index parțial și acoperitor (WHERE + INCLUDE) pentru comenzi active
Dacă 95% din comenzi sunt istorice (livrata) și interogăm frecvent doar comenzile in_procesare, un index parțial ocupă doar 5% din spațiu.
CREATE INDEX CONCURRENTLY idx_comenzi_active_client
ON comenzi (client_id, plasata_la DESC)
INCLUDE (total_lei)
WHERE status = 'in_procesare';
Rezultat interogare
CREATE INDEX
Greșeli frecvente
- Rularea unui
CREATE INDEXsimplu (fărăCONCURRENTLY) pe un tabel mare în producție: ia un lacătSHAREcare blochează toate comenzileINSERT,UPDATEșiDELETEpână la terminarea indexării. - Dacă un
CREATE INDEX CONCURRENTLYeșuează (de exemplu din cauza unui duplicat pe un indexUNIQUE), lasă în urmă un index marcatINVALID; verifică cu\d tabelși șterge-l cuDROP INDEX CONCURRENTLY nume_indexînainte de a reîncerca.
Comenzi și funcții înrudite
EXPLAIN (ANALYZE, BUFFERS): Afișează planul de execuție al optimizatorului, timpii reali pe fiecare nod și blocurile de memorie citite.JSONB și operatorii ->, ->>, @>, ?: Interoghează și filtrează documente binare JSONB folosind operatorii de extracție (->, ->>) și incluziune (@>, ?).VACUUM și ANALYZE: Recuperează spațiul ocupat de rândurile șterse/modificate (MVCC dead tuples) și actualizează statisticile pentru optimizator.