PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL-Index auf JSON

Ihre anderen beiden Indizes funktionieren einfach nicht, weil ->> Operator gibt text zurück , während Sie offensichtlich den jsonb haben Gin-Operator-Klassen im Auge. Beachten Sie, dass Sie nur json erwähnen , aber Sie brauchen eigentlich jsonb für erweiterte Indizierungsfunktionen.

Um die beste Indizierungsstrategie auszuarbeiten, müssten Sie genauer definieren, welche Abfragen abgedeckt werden sollen. Interessieren Sie sich nur für Kühe? Oder alle Tiere / alle Tags? Welche Operatoren sind möglich? Enthält Ihr JSON-Dokument auch Nichttierschlüssel? Was tun mit denen? Möchten Sie Zeilen in den Index aufnehmen, in denen Kühe (oder was auch immer) überhaupt nicht im JSON-Dokument auftauchen?

Angenommen:

  • Wir interessieren uns nur für Kühe auf der ersten Nistebene.
  • Der Wert ist immer eine gültige integer .
  • Reihen ohne Kühe interessieren uns nicht.

Ich schlage einen funktionalen Btree-Index vor, ähnlich wie Sie ihn bereits haben, aber wandeln Sie den Wert in integer um . Ich nehme an, Sie möchten nicht, dass der Vergleich als text ausgewertet wird (wobei '2' größer als '1111' ist).

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

Der zusätzliche Satz Klammern ist für die Cast-Kurzschrift erforderlich, um die Syntax für den Indexausdruck eindeutig zu machen.

Verwenden Sie denselben Ausdruck in Ihren Abfragen, damit Postgres erkennt, dass der Index anwendbar ist:

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

Wenn Sie eine allgemeinere jsonb benötigen Index, betrachten Sie:

  • Was ist der richtige Index zum Abfragen von Strukturen in Arrays in Postgres jsonb?

Für ein bekanntes, statisches, triviales Anzahl der Tiere (wie Sie kommentiert haben), schlage ich Teilindizes vor wie:

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;

usw.

Möglicherweise müssen Sie der Abfrage die Indexbedingung hinzufügen:

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

Mag überflüssig erscheinen, kann aber notwendig sein. Testen Sie mit ANALYZE !