Una prima misura immediata sarebbe rendere la query che hai un po' più veloce:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
Il EXISTS
semi-join evita la duplicazione delle righe nella tabella intermedia quando più oggetti array corrispondono e la necessità di DISTINCT ON
nella query esterna. Ma è ancora solo leggermente più veloce.
Il problema principale è che vuoi testare un intervallo di valori interi , mentre esistente jsonb
operatori
non forniscono tale funzionalità.
Ci sono vari modi per aggirare questo. Non sapendo nulla di tutto ciò, ecco una soluzione "intelligente" che risolve l'esempio fornito. Il trucco è dividere l'intervallo in valori distinti e utilizzare jsonb
operatore di contenimento @>
:
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Supportato da un jsonb_path_ops
Indice GIN:
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Ma se i tuoi intervalli si estendono per più di una mano piena di valori interi, avrai bisogno di qualcosa di più generico. Come sempre , la soluzione migliore dipende dalla situazione completa:distribuzione dei dati, frequenze dei valori, intervalli tipici nelle query, valori NULL possibili?, dimensione delle righe, modelli di lettura/scrittura, ogni jsonb
value hanno uno o più age
corrispondenti chiave? ...
Risposta correlata con indice specializzato e molto veloce:
Correlati: