Dine andre to indekser vil ikke fungere, blot fordi ->>
operator returnerer text
, mens du åbenbart har jsonb
gin operatør klasser i tankerne. Bemærk, at du kun nævner json
, men du har faktisk brug for jsonb
for avancerede indekseringsfunktioner.
For at finde den bedste indekseringsstrategi, skal du definere nærmere, hvilke forespørgsler der skal dækkes. Er du kun interesseret i køer? Eller alle dyr / alle mærker? Hvilke operatører er mulige? Indeholder dit JSON-dokument også ikke-dyrnøgler? Hvad skal man gøre med dem? Vil du inkludere rækker i indekset, hvor køer (eller hvad som helst) slet ikke vises i JSON-dokumentet?
Forudsat:
- Vi er kun interesserede i køer på det første niveau af rede.
- Værdien er altid et gyldigt
integer
. - Vi er ikke interesserede i rækker uden køer.
Jeg foreslår et funktionelt btree-indeks, ligesom du allerede har, men cast værdien til integer
. Jeg formoder ikke, at du vil have sammenligningen vurderet som text
(hvor '2' er større end '1111').
CREATE INDEX animal_index ON farm (((animal ->> 'cow')::int)); -- !
Det ekstra sæt parenteser er påkrævet for cast-stenografien for at gøre syntaksen for indeksudtrykket utvetydig.
Brug det samme udtryk i dine forespørgsler for at få Postgres til at indse, at indekset er anvendeligt:
SELECT * FROM farm WHERE (animal ->> 'cow')::int > 3;
Hvis du har brug for en mere generisk jsonb
indeks, overvej:
- Hvad er det korrekte indeks for at forespørge strukturer i arrays i Postgres jsonb?
For en kendt, statisk, triviel antal dyr (som du kommenterede), foreslår jeg delvise indekser som:
CREATE INDEX animal_index ON farm (((animal ->> 'cow')::int))
WHERE (animal ->> 'cow') IS NOT NULL;
CREATE INDEX animal_index ON farm (((animal ->> 'chicken')::int))
WHERE (animal ->> 'chicken') IS NOT NULL;
osv.
Du skal muligvis tilføje indeksbetingelsen til forespørgslen:
SELECT * FROM farm
WHERE (animal ->> 'cow')::int > 3
AND (animal ->> 'cow') IS NOT NULL;
Kan virke overflødigt, men kan være nødvendigt. Test med ANALYZE
!