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

GIN-Index für Spalte smallint[] nicht verwendet oder Fehleroperator ist nicht eindeutig

Lösung

Höchstwahrscheinlich die Lösung soll den Operator schemaqualifizieren:

SELECT *
FROM   test
WHERE  tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER  BY id
LIMIT  100;

Warum?

Es ist ein Problem der Operatorauflösung (in Kombination mit Typauflösung und Umwandlungskontext).

In Standard-Postgres gibt es nur einen einzigen Kandidatenoperator anyarray @> anyarray , das ist es, was Sie wollen.

Ihr Setup würde problemlos funktionieren, wenn Sie das zusätzliche Modul intarray nicht installiert hätten (meine Vermutung), die einen weiteren Operator für integer[] @> integer[] bereitstellt .

Daher wäre eine andere Lösung die Verwendung von integer[] stattdessen und haben einen GIN-Index mit dem gin__int_ops Betreiberklasse. Oder versuchen Sie es mit (Standard für Intarray) gist__int_ops Index. Beide könnten schneller sein, aber beide erlauben keine NULL-Werte.
Oder Sie könnten das intarray umbenennen Operator @> zu disambiguieren. (Das würde ich nicht tun. Es entstehen Upgrade- und Portabilitätsprobleme.)

Für Ausdrücke mit mindestens einem Operanden vom Typ integer[] , Postgres weiß, welchen Operator es auswählen muss:den Intarray-Operator. Aber dann ist der Index nicht anwendbar , da der Intarray-Operator nur mit integer arbeitet (int4 ) nicht int2 . Und Indizes sind strikt an Operatoren gebunden:

  • Kann PostgreSQL Array-Spalten indizieren?
  • Verhalten von PostgreSQL bei Vorhandensein von zwei verschiedenen Arten von Indizes für dieselbe Spalte

Aber für int2[] @> int2[] , Postgres ist nicht in der Lage, den besten Operator zu bestimmen. Beide scheinen gleichermaßen anwendbar zu sein. Da der Standardoperator in pg_catalog bereitgestellt wird Schema und der Intarray-Operator wird in public bereitgestellt Schema (standardmäßig - oder wo auch immer Sie die Erweiterung installiert haben), können Sie helfen, das Rätsel zu lösen, indem Sie den Operator mit OPERATOR() schemaqualifizieren bauen. Verwandte:

  • Arrays auf Gleichheit vergleichen, Reihenfolge der Elemente ignorieren

Die Fehlermeldung, die Sie erhalten, ist etwas irreführend. Aber wenn Sie genau hinsehen, gibt es einen HINT Zeile hinzugefügt, die Hinweise (Tada!) in die richtige Richtung:

ERROR:  operator is not unique: smallint[] @> smallint[]
LINE 1: SELECT NULL::int2[] @> NULL::int2[]
                            ^
HINT:  Could not choose a best candidate operator. You might need to add explicit type casts.

Sie können vorhandene Operatorkandidaten für @> untersuchen mit:

SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM   pg_operator o
JOIN   pg_namespace n ON n.oid = o.oprnamespace
WHERE  oprname = '@>';

Eine andere alternative Lösung wäre, vorübergehend (!) einen anderen Suchpfad festzulegen, sodass nur der gewünschte Operator gefunden wird. In derselben Transaktion:

SET LOCAL search_path = pg_catalog;
SELECT ...

Aber dann müssen Sie alle Tabellen in der Abfrage schemaqualifizieren.

Über den Besetzungskontext:

  • Generieren Sie eine Reihe von Datumsangaben - verwenden Sie den Datumstyp als Eingabe

Sie könnten Ändern Sie den castcontext von int2 -> int4 . Aber ich rate dringend davon ab. Zu viele mögliche Nebenwirkungen:

  • Gibt es eine Möglichkeit, den Datentyp von postgresql 9.3 so umzuwandeln, dass er nur eine Seite betrifft