sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL-index op JSON

Uw andere twee indexen werken niet alleen omdat de ->> operator retourneert text , terwijl je duidelijk de jsonb . hebt gin-operatorklassen in gedachten. Let op:je vermeldt alleen json , maar je hebt eigenlijk jsonb . nodig voor geavanceerde indexeringsmogelijkheden.

Om de beste indexeringsstrategie te bepalen, moet u nauwkeuriger definiëren welke zoekopdrachten u wilt behandelen. Ben je alleen geïnteresseerd in koeien? Of alle dieren / alle tags? Welke operatoren zijn mogelijk? Bevat uw JSON-document ook niet-dierlijke sleutels? Wat te doen met die? Wil je rijen in de index opnemen waar koeien (of wat dan ook) helemaal niet in het JSON-document voorkomen?

Ervan uitgaande:

  • We zijn alleen geïnteresseerd in koeien op het eerste nestniveau.
  • De waarde is altijd een geldig integer .
  • Wij zijn niet geïnteresseerd in rijen zonder koeien.

Ik stel een functionele btree-index voor, net zoals je al hebt gedaan, maar cast de waarde naar integer . Ik denk niet dat je wilt dat de vergelijking wordt geëvalueerd als text (waarbij '2' groter is dan '1111').

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

De extra set haakjes is vereist voor de cast-steno om de syntaxis voor de indexuitdrukking ondubbelzinnig te maken.

Gebruik dezelfde uitdrukking in uw zoekopdrachten om Postgres te laten beseffen dat de index van toepassing is:

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

Als u een meer generieke jsonb nodig heeft index, overweeg:

  • Wat is de juiste index voor het opvragen van structuren in arrays in Postgres jsonb?

Voor een bekend, statisch, triviaal aantal dieren (zoals je hebt opgemerkt), stel ik gedeeltelijke indexen voor zoals:

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;

enz.

Mogelijk moet u de indexvoorwaarde aan de zoekopdracht toevoegen:

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

Lijkt misschien overbodig, maar kan nodig zijn. Test met ANALYZE !




  1. Hoe dubbele gebruikersnamen voorkomen wanneer mensen zich registreren?

  2. Hoe de naamreeks in mysql te splitsen?

  3. MySQL op Azure Performance Benchmark – ScaleGrid vs. Azure Database

  4. Zelf meedoen in orakel met voorbeelden