Une première mesure immédiate serait de rendre la requête que vous avez un peu plus rapide :
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
Le EXISTS
la semi-jointure évite la duplication des lignes dans la table intermédiaire lorsque plusieurs objets de tableau correspondent - et le besoin de DISTINCT ON
dans la requête externe. Mais ce n'est encore que légèrement plus rapide.
Le problème principal est que vous voulez tester une plage de valeurs entières , tandis que jsonb
opérateurs
ne fournissent pas une telle fonctionnalité.
Il existe différentes façons de contourner cela. Ne sachant rien de tout cela, voici une solution "intelligente" qui résout l'exemple donné. L'astuce consiste à diviser la plage en valeurs distinctes et à utiliser le jsonb
opérateur de confinement @>
:
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Pris en charge par un jsonb_path_ops
Indice GIN :
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Mais si vos plages s'étendent sur plus d'une poignée de valeurs entières, vous aurez besoin de quelque chose de plus générique. Comme toujours , la meilleure solution dépend de la situation complète :distribution des données, fréquences des valeurs, plages types dans les requêtes, valeurs NULL possibles ?, taille des lignes, modèles de lecture/écriture, est-ce que chaque jsonb
valeur ont un ou plusieurs age
correspondants clé? ...
Réponse connexe avec index spécialisé et très rapide :
Connexe :
- Index pour trouver un élément dans un tableau JSON
- Utilisation des index dans JSON tableau dans PostgreSQL