sql >> Database >  >> RDS >> PostgreSQL

Versnel de bereiktest voor sleutelwaarden die zijn genest in jsonb-array van objecten

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:



  1. Kan de 'libpq-fe.h header niet vinden bij het installeren van pg gem

  2. Prestaties van MySql XML-functies?

  3. Sql-query leeg resultaat op php-code

  4. Maximale uitvoeringstijd van 30 seconden overschreden