PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Indice PostgreSQL su JSON

Gli altri due indici non funzioneranno semplicemente perché ->> l'operatore restituisce text , mentre ovviamente hai il jsonb classi di operatori gin in mente. Nota che menzioni solo json , ma in realtà hai bisogno di jsonb per funzionalità di indicizzazione avanzate.

Per elaborare la migliore strategia di indicizzazione, dovresti definire più da vicino quali query coprire. Ti interessano solo le mucche? O tutti gli animali/tutti i tag? Quali operatori sono possibili? Il tuo documento JSON include anche chiavi non animali? Cosa fare con quelli? Vuoi includere le righe nell'indice in cui le mucche (o altro) non vengono affatto visualizzate nel documento JSON?

Supponendo:

  • Ci interessano solo le mucche al primo livello di nidificazione.
  • Il valore è sempre un integer valido .
  • Non ci interessano i filari senza mucche.

Suggerisco un indice btree funzionale, proprio come hai già fatto, ma lancia il valore su integer . Suppongo che non vorresti che il confronto fosse valutato come text (dove '2' è maggiore di '1111').

CREATE INDEX animal_index ON farm (((animal ->> 'cow')::int));  -- !

Il set aggiuntivo di parentesi è necessario affinché la scorciatoia cast renda non ambigua la sintassi per l'espressione dell'indice.

Usa la stessa espressione nelle tue query per far capire a Postgres che l'indice è applicabile:

SELECT * FROM farm WHERE (animal ->> 'cow')::int > 3;

Se hai bisogno di un jsonb più generico indice, considera:

  • Qual ​​è l'indice corretto per interrogare le strutture negli array in Postgres jsonb?

Per un noto, statico, banale numero di animali (come hai commentato), suggerisco indici parziali come:

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;

ecc.

Potrebbe essere necessario aggiungere la condizione dell'indice alla query:

SELECT * FROM farm
WHERE (animal ->> 'cow')::int > 3
AND   (animal ->> 'cow') IS NOT NULL; 

Può sembrare ridondante, ma può essere necessario. Prova con ANALYZE !