sql >> Base de Datos >  >> RDS >> PostgreSQL

El índice GIN en la columna smallint[] no se usa o el operador de error no es único

Solución

Lo más probable es que la solución es calificar el esquema del operador:

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

¿Por qué?

Es un problema de resolución del operador (en combinación con resolución de tipo y contexto de transmisión).

En Postgres estándar, solo hay un único operador candidato anyarray @> anyarray , ese es el que quieres.

Su configuración funcionaría bien si no hubiera instalado el módulo adicional intarray (mi suposición), que proporciona otro operador para integer[] @> integer[] .

Por lo tanto, otra solución sería usar integer[] en su lugar y tener un índice GIN con el gin__int_ops clase de operador. O pruebe el (predeterminado para intarray) gist__int_ops índice. Cualquiera de los dos podría ser más rápido, pero ambos no permiten valores NULOS.
O podría cambiar el nombre del intarray operador @> para desambiguar. (Yo no haría eso. Se producen problemas de actualización y portabilidad).

Para expresiones que involucran al menos un operando de tipo integer[] , Postgres sabe qué operador elegir:el operador intraray. Pero entonces el índice no es aplicable , porque el operador intraray solo opera en integer (int4 ) no int2 . Y los índices están estrictamente vinculados a los operadores:

  • ¿Puede PostgreSQL indexar columnas de matrices?
  • Comportamiento de PostgreSQL en presencia de dos tipos diferentes de índices en la misma columna

Pero para int2[] @> int2[] , Postgres no puede decidir cuál es el mejor operador. Ambos parecen igualmente aplicables. Dado que el operador predeterminado se proporciona en el pg_catalog schema y el operador intraray se proporciona en el public esquema (de forma predeterminada, o donde haya instalado la extensión), puede ayudar a resolver el enigma calificando al operador con el OPERATOR() construir. Relacionado:

  • Compara matrices para la igualdad, ignorando el orden de los elementos

El mensaje de error que recibe es un poco engañoso. Pero si miras de cerca, hay una HINT línea agregada que sugiere (¡tada!) en la dirección correcta:

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.

Puede investigar los candidatos a operadores existentes para @> con:

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

Otra solución alternativa sería establecer temporalmente (!) una ruta de búsqueda diferente, de modo que solo se encuentre el operador deseado. En la misma transacción:

SET LOCAL search_path = pg_catalog;
SELECT ...

Pero luego debe calificar con esquema todas las tablas en la consulta.

Acerca del contexto de transmisión:

  • Generar series de fechas - usando el tipo de fecha como entrada

podrías cambiar el castcontext de int2 -> int4 . Pero lo desaconsejo fuertemente. Demasiados posibles efectos secundarios:

  • ¿Hay alguna forma de convertir el tipo de datos postgresql 9.3 para que pueda afectar solo a un lado?