PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

GIN индекс в колоната smallint[] не се използва или операторът за грешка не е уникален

Решение

Най-вероятно решението е да се квалифицира по схема на оператора:

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

Защо?

Това е проблем соператорската резолюция (в комбинация с разделителна способност на типа и контекст на предаване).

В стандартния Postgres има само един оператор кандидат anyarray @> anyarray , това е този, който искате.

Вашата настройка би работила добре, ако не сте инсталирали допълнителния модулен intarray (моето предположение), което предоставя друг оператор за integer[] @> integer[] .

Следователно, друго решение би било да се използва integer[] вместо това и да има GIN индекс с gin__int_ops оператор клас. Или опитайте (по подразбиране за intarray) gist__int_ops индекс. И двете може да са по-бързи, но и двете не позволяват NULL стойности.
Или можете да преименувате intarray оператор @> да се уточнява. (Не бих направил това. Възникват проблеми с надстройката и преносимостта.)

За изрази, включващи поне един операнд от тип integer[] , Postgres знае кой оператор да избере:операторът intarray. Но тогава индексът не е приложим , тъй като операторът intarray работи само с integer (int4 ) не int2 . И индексите са строго обвързани с операторите:

  • Може ли PostgreSQL да индексира колони от масиви?
  • Поведение на PostgreSQL при наличие на два различни типа индекси в една и съща колона

Но за int2[] @> int2[] , Postgres не може да определи най-добрия оператор. И двете изглеждат еднакво приложими. Тъй като операторът по подразбиране е предоставен в pg_catalog схемата и операторът intarray се предоставя в public схема (по подразбиране - или където и да сте инсталирали разширението), можете да помогнете за разрешаването на загадката, като квалифицирате оператора по схема с OPERATOR() конструкция. Свързано:

  • Сравнете масивите за равенство, като игнорирате реда на елементите

Съобщението за грешка, което получавате, е малко подвеждащо. Но ако погледнете внимателно, има HINT добавен ред, който намеква (така!) в правилната посока:

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.

Можете да проучите съществуващи кандидати за оператор за @> с:

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

Друго алтернативно решение би било временно(!) да зададете различен search_path, така че да се намери само желания оператор. В същата транзакция:

SET LOCAL search_path = pg_catalog;
SELECT ...

Но тогава трябва да квалифицирате схематично всички таблици в заявката.

Относно контекста на предаване:

  • Генерирайте поредица от дати – като използвате тип дата като вход

Вие можете променете castcontext на int2 -> int4 . Но аз силно не го съветвам. Твърде много възможни странични ефекти:

  • Има ли някакъв начин за прехвърляне на тип данни на postgresql 9.3, така че да може да засегне само едната страна



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Диалектът трябва да бъде изрично предоставен от v4.0.0

  2. 3 начина за изброяване на всички тригери за дадена таблица в PostgreSQL

  3. Съвети за внедряване на хибриден облак на PostgreSQL

  4. Генерирайте sql с подзаявка като колона в оператор select с помощта на SQLAlchemy

  5. Ред за връщане на SQL ред