PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

O índice GIN na coluna smallint[] não é usado ou o operador de erro não é exclusivo

Solução


Muito provavelmente, a solução é qualificar o operador pelo esquema:
SELECT *
FROM   test
WHERE  tagged OPERATOR([email protected]>) '{11}'::int2[]
ORDER  BY id
LIMIT  100;

Por quê?


É um problema de resolução do operador (em combinação com resolução de tipo e contexto de conversão).

No Postgres padrão, existe apenas um único operador candidato anyarray @> anyarray , esse é o que você quer.

Sua configuração funcionaria bem se você não tivesse instalado o módulo adicional intarray (minha suposição), que fornece outro operador para integer[] @> integer[] .

Portanto, outra solução seria usar integer[] em vez disso e ter um índice GIN com o gin__int_ops classe de operador. Ou tente o (padrão para intarray) gist__int_ops índice. Qualquer um pode ser mais rápido, mas ambos não permitem valores NULL.
Ou você pode renomear o intarray operador @> para desambiguar. (Eu não faria isso. Problemas de atualização e portabilidade ocorrem.)


Para expressões envolvendo pelo menos um operando do tipo integer[] , o Postgres sabe qual operador escolher:o operador intarray. Mas então o índice não é aplicável , porque o operador intarray opera apenas em integer (int4 ) não int2 . E os índices são estritamente vinculados aos operadores:
  • O PostgreSQL pode indexar colunas de array?
  • Comportamento do PostgreSQL na presença de dois tipos diferentes de índices na mesma coluna

Mas para int2[] @> int2[] , o Postgres não consegue decidir o melhor operador. Ambos parecem igualmente aplicáveis. Como o operador padrão é fornecido no pg_catalog esquema e o operador intarray é fornecido no public esquema (por padrão - ou onde quer que você instalou a extensão), você pode ajudar a resolver o enigma qualificando o operador pelo esquema com o OPERATOR() construir. Relacionado:
  • Compare arrays para igualdade, ignorando a ordem dos elementos

A mensagem de erro que você recebe é um pouco enganosa. Mas se você olhar de perto, há uma HINT linha adicionada que sugere (tada!) na direção certa:
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.

Você pode investigar candidatos a operadores existentes para @> com:
SELECT o.oid, *, oprleft::regtype, oprright::regtype, n.nspname
FROM   pg_operator o
JOIN   pg_namespace n ON n.oid = o.oprnamespace
WHERE  oprname = '@>';

Outra solução alternativa seria definir temporariamente(!) um search_path diferente, para que apenas o operador desejado seja encontrado. Na mesma transação:
SET LOCAL search_path = pg_catalog;
SELECT ...

Mas então você precisa qualificar pelo esquema todas as tabelas na consulta.

Sobre o contexto do elenco:
  • Gerar séries de datas - usando o tipo de data como entrada

Você poderia altere o castcontext de int2 -> int4 . Mas eu aconselho fortemente contra isso. Muitos efeitos colaterais possíveis:
  • Existe alguma maneira de converter o tipo de dados postgresql 9.3 para que ele possa afetar apenas um lado