Ich habe eine sehr einfache JSON-Tabelle, die ich mit einigen Beispieldaten fülle:
CREATE TABLE jsonthings(d JSONB NOT NULL);
INSERT INTO jsonthings VALUES ('{"name":"First","tags":["foo"]}');
INSERT INTO jsonthings VALUES ('{"name":"Second","tags":["foo","bar"]}');
INSERT INTO jsonthings VALUES ('{"name":"Third","tags":["bar","baz"]}');
INSERT INTO jsonthings VALUES ('{"name":"Fourth","tags":["baz"]}');
CREATE INDEX ON jsonthings USING GIN(d);
Und ich versuche, den Index beim Ausführen von a zu verwenden SELECT
. Ein einfaches SELECT
Abrufen der Zeilen, in denen der Wert ein einzelnes Element ist, funktioniert einwandfrei:
SELECT d FROM jsonthings WHERE d @> '{"name":"First"}';
Wenn name
ich jedoch versuche, eine Abfrage auszuführen, die mehr als einem Wert von entspricht, kann ich nicht herausfinden, wie der Index verwendet wird. Ich habe es versucht:
SELECT d FROM jsonthings WHERE d->>'name' = ANY(ARRAY['First', 'Second']);
SELECT d FROM jsonthings WHERE d->'name' ?| ARRAY['First', 'Second'];
SELECT d FROM jsonthings WHERE d#>'{name}' ?| ARRAY['First','Second'];
und alle zeigen einen sequentiellen Scan der Tabelle (ich verwende enable_seqscan=false
, um die Indexverwendung zu erzwingen, wenn möglich). Gibt es eine Möglichkeit, die Abfrage so umzuschreiben, dass sie einen Index verwendet? Mir ist bewusst, dass ich Folgendes tun könnte:
SELECT * FROM jsonthings WHERE d @> '{"name":"First"}' OR d @> '{"name":"Second"}';
Aber dann habe ich eine Abfrage mit variabler Länge und gehe durch JDBC, sodass die Vorteile der Abfrage als PreparedStatement verloren gehen.
Ich bin auch daran interessiert, eine ähnliche Abfrage für eine Reihe von Elementen im tags
Schlüssel zu sehen, z.
SELECT d FROM jsonthings WHERE d @> '{"tags":["foo"]}' OR d @> '{"tags":["bar"]}';
aber unter Verwendung einer ARRAY
statt mehrerer Bedingungen und unter Verwendung eines Index.
Dies ist auf PostgreSql 9.4.