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

GIN-indeks på smallint[]-kolonnen bruges ikke, eller fejloperatoren er ikke unik

Løsning

Sandsynligvis løsningen er at skemakvalificere operatøren:

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

Hvorfor?

Det er et problem med operatøropløsning (i kombination med typeopløsning og cast-kontekst).

I standard Postgres er der kun en enkelt kandidatoperator anyarray @> anyarray , det er den, du vil have.

Din opsætning ville fungere fint, hvis du ikke havde installeret det ekstra modul intarray (min antagelse), som giver en anden operator for integer[] @> integer[] .

Derfor ville en anden løsning være at bruge integer[] i stedet og have et GIN-indeks med gin__int_ops operatørklasse. Eller prøv (standard for intarray) gist__int_ops indeks. Begge kan være hurtigere, men begge tillader ikke NULL-værdier.
Eller du kan omdøbe intarray operatør @> at tvetydige. (Det ville jeg ikke gøre. Problemer med opgradering og portabilitet opstår.)

For udtryk, der involverer mindst én operand af typen integer[] , Postgres ved, hvilken operatør der skal vælges:Intarray-operatoren. Men så er indekset ikke anvendeligt , fordi intarray-operatoren kun fungerer på integer (int4 ) ikke int2 . Og indekser er strengt bundet til operatører:

  • Kan PostgreSQL indeksere array-kolonner?
  • PostgreSQL-adfærd ved tilstedeværelse af to forskellige typer indekser i samme kolonne

Men for int2[] @> int2[] , Postgres er ikke i stand til at bestemme den bedste operatør. Begge virker lige anvendelige. Da standardoperatøren er angivet i pg_catalog skemaet og intarray-operatoren findes i public skema (som standard - eller hvor end du har installeret udvidelsen), kan du hjælpe med at løse gåden ved at skemakvalificere operatøren med OPERATOR() konstruere. Relateret:

  • Sammenlign arrays for lighed, ignorer rækkefølgen af ​​elementer

Den fejlmeddelelse du får er en smule misvisende. Men hvis du ser godt efter, er der et HINT linje tilføjet, som antyder (tada!) i den rigtige retning:

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.

Du kan undersøge eksisterende operatørkandidater for @> med:

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

En anden alternativ løsning ville være midlertidigt(!) at indstille en anden søgesti, så kun den ønskede operator findes. I samme transaktion:

SET LOCAL search_path = pg_catalog;
SELECT ...

Men så skal du skema-kvalificere alle tabeller i forespørgslen.

Om rollebesætningskontekst:

  • Generer serier af datoer - brug datotype som input

Du kunne ændre castcontext af int2 -> int4 . Men jeg fraråder det kraftigt. For mange mulige bivirkninger:

  • Er der nogen måde at caste postgresql 9.3 datatype, så den kun kan påvirke den ene side



  1. Dvale:Opret indeks

  2. Sådan får du kortdagens navn fra en dato i MariaDB

  3. Sådan bruges Where-klausulen i Select Statement i SQL Server - SQL Server / TSQL Tutorial Del 109

  4. Smukke blokke af kedelplade