Eine erste Sofortmaßnahme wäre, die Abfrage etwas schneller zu machen:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
Der EXISTS
Semi-Join vermeidet die Duplizierung von Zeilen in der Zwischentabelle, wenn mehrere Array-Objekte übereinstimmen - und die Notwendigkeit von DISTINCT ON
in der äußeren Abfrage. Aber das ist nur geringfügig schneller.
Das Kernproblem besteht darin, dass Sie auf einen Bereich ganzzahliger Werte testen möchten , während vorhandene jsonb
Operatoren
stellen solche Funktionen nicht bereit.
Es gibt verschiedene Möglichkeiten, dies zu umgehen. Nichts davon wissend, hier ist eine "intelligente" Lösung, die das gegebene Beispiel löst. Der Trick besteht darin, den Bereich in verschiedene Werte aufzuteilen und den jsonb
zu verwenden Containment-Operator @>
:
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Unterstützt von einem jsonb_path_ops
GIN-Index:
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Wenn Ihre Bereiche jedoch mehr als eine Handvoll ganzzahliger Werte umfassen, benötigen Sie etwas Allgemeineres. Wie immer , die beste Lösung hängt von der Gesamtsituation ab:Datenverteilung, Wertehäufigkeiten, typische Bereiche in Abfragen, NULL-Werte möglich?, Zeilengröße, Lese-/Schreibmuster, funktioniert jeder jsonb
Wert haben mindestens ein übereinstimmendes age
Schlüssel? ...
Verwandte Antwort mit spezialisiertem, sehr schnellem Index:
Verwandte:
- Index zum Auffinden eines Elements in einem JSON-Array
- Verwendung von Indizes in json -Array in PostgreSQL