Een eerste onmiddellijke maatregel zou zijn om de vraag die je hebt wat sneller te maken:
SELECT *
FROM parents p
WHERE EXISTS (
SELECT FROM jsonb_array_elements(p.children) c
WHERE (c->>'age')::int BETWEEN 10 AND 12
);
De EXISTS
semi-join voorkomt duplicatie van rijen in de tussentabel wanneer meerdere array-objecten overeenkomen - en de noodzaak van DISTINCT ON
in de buitenste vraag. Maar dat is nog maar een klein beetje sneller.
Het kernprobleem is dat u wilt testen op een bereik van gehele waarden , terwijl bestaande jsonb
operators
bieden dergelijke functionaliteit niet.
Er zijn verschillende manieren om dit te omzeilen. Omdat ik hier niets van weet, is hier een "slimme" oplossing die het gegeven voorbeeld oplost. De truc is om het bereik te splitsen in verschillende waarden en de jsonb
. te gebruiken insluitingsoperator @>
:
SELECT *
FROM parents p
WHERE (p.children @> '[{"age": 10}]'
OR p.children @> '[{"age": 11}]'
OR p.children @> '[{"age": 12}]');
Ondersteund door een jsonb_path_ops
GIN-index:
CREATE INDEX parents_children_gin_idx ON parents USING gin (children jsonb_path_ops);
Maar als uw bereiken meer dan een handvol gehele waarden omvatten, heeft u iets generieker nodig. Zoals altijd , de beste oplossing hangt af van de volledige situatie:gegevensdistributie, waardefrequenties, typische bereiken in zoekopdrachten, NULL-waarden mogelijk?, rijgrootte, lees-/schrijfpatronen, doet elke jsonb
waarde hebben een of meer overeenkomende age
sleutel? ...
Gerelateerd antwoord met gespecialiseerde, zeer snelle index:
Gerelateerd:
- Index voor het vinden van een element in een JSON-array
- Indices gebruiken in json array in PostgreSQL