sql >> Databasteknik >  >> RDS >> PostgreSQL

GIN-index på smallint[] kolumn används inte eller feloperatorn är inte unik

Lösning

Mest troligt är lösningen är att schemakvalificera operatören:

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

Varför?

Det är ett problem med operatörsupplösning (i kombination med typupplösning och castkontext).

I standard Postgres finns det bara en enda kandidatoperator anyarray @> anyarray , det är den du vill ha.

Din installation skulle fungera bra om du inte hade installerat extra modul intarray (mitt antagande), som tillhandahåller en annan operator för integer[] @> integer[] .

Därför skulle en annan lösning vara att använda integer[] istället och ha ett GIN-index med gin__int_ops operatörsklass. Eller prova (standard för intarray) gist__int_ops index. Båda kan vara snabbare, men båda tillåter inte NULL-värden.
Eller så kan du byta namn på intarray operator @> att disambiguera. (Jag skulle inte göra det. Uppgraderings- och portabilitetsproblem uppstår.)

För uttryck som involverar minst en operand av typen integer[] , Postgres vet vilken operatör som ska väljas:intarray-operatorn. Men då är indexet inte tillämpligt , eftersom intarray-operatorn bara fungerar på integer (int4 ) inte int2 . Och index är strikt bundna till operatörer:

  • Kan PostgreSQL indexera arraykolumner?
  • PostgreSQL-beteende i närvaro av två olika typer av index i samma kolumn

Men för int2[] @> int2[] , Postgres kan inte bestämma den bästa operatören. Båda verkar lika tillämpliga. Eftersom standardoperatorn finns i pg_catalog schemat och intarray-operatorn tillhandahålls i public schema (som standard - eller var du än installerade tillägget), kan du hjälpa till att lösa gåtan genom att schemakvalificera operatören med OPERATOR() konstruera. Relaterat:

  • Jämför matriser för likhet, ignorera ordningen på elementen

Felmeddelandet du får är lite missvisande. Men om du tittar noga så finns det ett HINT rad tillagd som antyder (tada!) i rätt riktning:

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öka befintliga operatörskandidater för @> 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 annan alternativ lösning skulle vara att tillfälligt(!) ställa in en annan sökväg, så att endast den önskade operatorn hittas. I samma transaktion:

SET LOCAL search_path = pg_catalog;
SELECT ...

Men då måste du schemakvalificera alla tabeller i frågan.

Om medverkande sammanhang:

  • Generera serier av datum - använd datumtyp som indata

Du kunde ändra castcontext av int2 -> int4 . Men jag avråder starkt från det. För många möjliga biverkningar:

  • Finns det något sätt att casta postgresql 9.3 datatyp så att den bara kan påverka en sida



  1. Meddelar att SQL Compliance Manager 5.9 är allmänt tillgänglig

  2. Hur man får ålder i år, månader och dagar med Oracle

  3. Hur man får det aktuella datumet i Oracle

  4. Använd NEWSEQUENTIALID() för att skapa en inkrementerande GUID i SQL Server