Lavorare con dati JSON in PostgreSQL è una figata, ma come ogni strumento potente, serve un po' di attenzione. Anche un piccolo errore può trasformare la tua query in un vero rompicapo. Oggi ci concentriamo di nuovo sugli errori più comuni che capitano con JSON e JSONB in PostgreSQL, e su come evitarli senza impazzire.
Problema 1: usare JSON invece di JSONB
Tanti che iniziano pensano che il tipo JSON sia la scelta migliore per salvare dati in formato JSON. In realtà, JSON in PostgreSQL salva tutto come testo, e questo può rallentare un sacco le ricerche e i filtri.
Esempio di errore:
CREATE TABLE products (
id SERIAL PRIMARY KEY,
details JSON
);
INSERT INTO products (details) VALUES ('{"nome": "Laptop", "prezzo": 1000}');
INSERT INTO products (details) VALUES ('{"nome": "Laptop", "prezzo": 1000}');
Se provi a filtrare per chiave (prezzo), sarà molto più lento rispetto a JSONB.
Come risolvere: usa JSONB se pensi di filtrare spesso o accedere ai dati.
CREATE TABLE products (
id SERIAL PRIMARY KEY,
details JSONB
);
Problema 2: mancanza di indici per JSONB
JSONB è super potente, ma senza indici le query complesse possono diventare lente come una lumaca.
Esempio di errore: supponiamo di avere una tabella con la colonna details dove salviamo un sacco di oggetti JSON:
SELECT * FROM products WHERE details->>'nome' = 'Laptop';
Se i dati non sono indicizzati, il server farà una scansione completa della tabella (full table scan), perdendo un sacco di tempo.
Come risolvere: crea un indice GIN per velocizzare la ricerca sulle chiavi:
CREATE INDEX idx_details_nome ON products USING gin (details jsonb_path_ops);
Problema 3: errori nell’estrazione di dati annidati
Estrarre dati da oggetti o array annidati può essere un casino, soprattutto se non conosci la differenza tra gli operatori -> e ->>.
Esempio di errore:
SELECT details->'prezzo' FROM products;
Questa query ti restituisce il valore in formato JSON, non come stringa ("1000" invece di 1000). Se vuoi proprio il valore, devi usare ->>:
SELECT details->>'prezzo' FROM products;
Problema 4: uso sbagliato degli operatori
Magari hai visto l’operatore @> e hai pensato: "Sembra figo, usiamolo sempre!" Ma se non sai come funziona, rischi risultati strani.
Esempio di errore:
SELECT * FROM products WHERE details @> '{"prezzo": 1000}';
Questa query funziona solo se prezzo è un numero nel JSON. Se il valore è salvato come stringa "1000", la query non restituisce nulla.
Come risolvere: fai attenzione ai tipi di dato nel JSON:
SELECT * FROM products WHERE details->>'prezzo' = '1000';
Problema 5: Oggetti JSON troppo grandi
Salvare oggetti JSON enormi senza ottimizzare può rallentare di brutto le query. E anche leggere o modificare una piccola parte dei dati dentro JSONB richiede di processare tutto l’oggetto.
Come risolvere: se alcune chiavi le usi spesso, mettile in colonne separate della tabella. Tipo così:
ALTER TABLE products ADD COLUMN prezzo NUMERIC;
UPDATE products SET prezzo = (details->>'prezzo')::NUMERIC;
Così puoi filtrare e ordinare i dati in modo efficiente senza dover smontare il JSONB ogni volta.
Problema 6: ricostruzione completa degli oggetti quando li modifichi
Quando usi funzioni tipo jsonb_set() o jsonb_insert(), PostgreSQL crea un nuovo oggetto JSONB da zero, e questo può costare caro in termini di performance.
Come risolvere: cerca di ridurre al minimo gli aggiornamenti su JSONB. Ad esempio, invece di aggiornare spesso un solo oggetto, raggruppa tutte le modifiche in una sola query:
UPDATE products
SET details = jsonb_set(details, '{prezzo}', '1500'::jsonb);
Problema 7: non capire la struttura degli array
Con JSONB anche gli array vanno trattati con attenzione. Supponiamo di avere un array così:
{
"etichette": ["elettronica", "laptop", "offerta"]
}
Vuoi controllare se c’è l’etichetta "laptop". Se usi male l’operatore @>, rischi di non trovare nulla, perché si aspetta un array, non una stringa.
Esempio di errore:
SELECT * FROM products WHERE details->'etichette' @> '"laptop"';
Come risolvere: Usa il formato giusto con l’operatore @>:
SELECT * FROM products WHERE details->'etichette' @> '["laptop"]';
Consigli per evitare errori
Per non impazzire con JSONB, segui questi consigli:
Scegli il tipo di dato giusto. Se lavori con tanti dati e filtri spesso, usa sempre JSONB invece di JSON.
Indicizza i dati. Se le query puntano spesso a certe chiavi, crea l’indice giusto (tipo GIN).
Controlla i dati prima di inserirli. Usa funzioni di validazione per verificare la struttura dei dati:
DO $$
BEGIN
IF jsonb_typeof('{"prezzo": 1000}'::jsonb->'prezzo') IS DISTINCT FROM 'number' THEN
RAISE EXCEPTION 'Il prezzo deve essere un numero';
END IF;
END $$;
Ottimizza la struttura dei dati. Se alcune chiavi sono usate più spesso di altre, estrai quelle in colonne separate della tabella.
Studia operatori e funzioni. Leggi bene la documentazione ufficiale di PostgreSQL per capire le differenze tra ->, ->>, @>, ?| e le altre funzioni.
JSON e JSONB possono diventare tuoi alleati quando lavori con dati flessibili e complessi. L’importante è scegliere bene gli strumenti e non cadere negli errori più comuni, così il tuo codice sarà veloce e facile da mantenere.
GO TO FULL VERSION