sql >> Databáze >  >> RDS >> PostgreSQL

Index GIN ve sloupci smallint[] není použit nebo operátor chyby není jedinečný

Řešení

S největší pravděpodobností řešení je kvalifikovat operátor schématu:

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

Proč?

Je to problém rozlišení operátora (v kombinaci s rozlišením typu a kontextem obsazení).

Ve standardním Postgresu existuje pouze jeden kandidátský operátor anyarray @> anyarray , to je ten, který chcete.

Vaše nastavení by fungovalo dobře, pokud byste nenainstalovali přídavný modul intarray (můj předpoklad), který poskytuje další operátor pro integer[] @> integer[] .

Dalším řešením by tedy bylo použití integer[] místo toho a mít index GIN s gin__int_ops třída operátorů. Nebo zkuste (výchozí pro intarray) gist__int_ops index. Obě mohou být rychlejší, ale obě neumožňují hodnoty NULL.
Nebo můžete přejmenovat intarray operátor @> vyjasnit. (To bych neudělal. Následují problémy s upgradem a přenositelností.)

Pro výrazy obsahující alespoň jeden operand typu integer[] , Postgres ví, který operátor vybrat:operátor intraray. Pak ale index nelze použít , protože operátor intarray pracuje pouze s integer (int4 ) ne int2 . A indexy jsou přísně vázány na operátory:

  • Může PostgreSQL indexovat sloupce pole?
  • Chování PostgreSQL v přítomnosti dvou různých typů indexů ve stejném sloupci

Ale pro int2[] @> int2[] , Postgres není schopen rozhodnout o nejlepším operátorovi. Oba se zdají být stejně použitelné. Protože výchozí operátor je uveden v pg_catalog schéma a operátor intarray jsou uvedeny v public schéma (ve výchozím nastavení – nebo kdekoli, kam jste rozšíření nainstalovali), můžete vyřešit hlavolam tím, že operátor kvalifikujete podle schématu pomocí OPERATOR() postavit. Související:

  • Porovnejte pole pro rovnost, ignorujte pořadí prvků

Chybová zpráva, kterou dostanete, je trochu zavádějící. Ale když se podíváte pozorně, je tu HINT přidán řádek, který naznačuje (tada!) správným směrem:

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.

Můžete prozkoumat stávající kandidáty na operátory pro @> s:

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

Dalším alternativním řešením by bylo dočasně(!) nastavit jinou cestu hledání, aby byl nalezen pouze požadovaný operátor. Ve stejné transakci:

SET LOCAL search_path = pg_catalog;
SELECT ...

Pak ale musíte kvalifikovat všechny tabulky v dotazu podle schématu.

O kontextu cast:

  • Generujte řadu dat – jako vstup použijte typ data

Mohli byste změnit castcontext z int2 -> int4 . Ale důrazně to nedoporučuji. Příliš mnoho možných vedlejších účinků:

  • Existuje nějaký způsob, jak přenést datový typ postgresql 9.3 tak, aby to mohlo ovlivnit pouze jednu stranu?



  1. Jak se nazývají trubky?

  2. Jak přidat název do záhlaví formuláře v aplikaci Access

  3. Užitečné tipy pro řešení běžných chyb v MySQL

  4. Funkce ADD_MONTHS() v Oracle