PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

L'index GIN sur la colonne smallint[] n'est pas utilisé ou l'opérateur d'erreur n'est pas unique

Solution

Très probablement, la solution est de qualifier schématiquement l'opérateur :

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

Pourquoi ?

C'est un problème de résolution de l'opérateur (en combinaison avec la résolution de type et le contexte de conversion).

Dans Postgres standard, il n'y a qu'un seul opérateur candidat anyarray @> anyarray , c'est celui que vous voulez.

Votre configuration fonctionnerait très bien si vous n'aviez pas installé le module supplémentaire intarray (mon hypothèse), qui fournit un autre opérateur pour integer[] @> integer[] .

Par conséquent, une autre solution serait d'utiliser integer[] à la place et avoir un index GIN avec le gin__int_ops classe d'opérateur. Ou essayez le (par défaut pour intarray) gist__int_ops indice. L'un ou l'autre peut être plus rapide, mais les deux n'autorisent pas les valeurs NULL.
Ou vous pouvez renommer le intarray opérateur @> pour lever l'ambiguïté. (Je ne ferais pas ça. Des problèmes de mise à niveau et de portabilité s'ensuivent.)

Pour les expressions comportant au moins un opérande de type integer[] , Postgres sait quel opérateur choisir :l'opérateur intarray. Mais alors l'index n'est pas applicable , car l'opérateur intra-rayon n'opère que sur integer (int4 ) pas int2 . Et les index sont strictement liés aux opérateurs :

  • Est-ce que PostgreSQL peut indexer les colonnes d'un tableau ?
  • Comportement de PostgreSQL en présence de deux types d'index différents sur la même colonne

Mais pour int2[] @> int2[] , Postgres est incapable de décider du meilleur opérateur. Les deux semblent également applicables. Puisque l'opérateur par défaut est fourni dans le pg_catalog schéma et l'opérateur intraray est fourni dans le public schema (par défaut - ou partout où vous avez installé l'extension), vous pouvez aider à résoudre l'énigme en qualifiant de schéma l'opérateur avec le OPERATOR() construction. Connexe :

  • Comparer les tableaux pour l'égalité, en ignorant l'ordre des éléments

Le message d'erreur que vous obtenez est un peu trompeur. Mais si vous regardez attentivement, il y a un HINT ligne ajoutée qui indique (tada !) dans la bonne direction :

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.

Vous pouvez rechercher des candidats opérateurs existants pour @> avec :

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

Une autre solution alternative serait de définir temporairement (!) un chemin de recherche différent, de sorte que seul l'opérateur souhaité soit trouvé. Dans la même transaction :

SET LOCAL search_path = pg_catalog;
SELECT ...

Mais ensuite, vous devez qualifier de schéma toutes les tables de la requête.

À propos du contexte de diffusion :

  • Générer une série de dates - en utilisant le type de date comme entrée

Vous pourriez changer le castcontext de int2 -> int4 . Mais je le déconseille fortement. Trop d'effets secondaires possibles :

  • Existe-t-il un moyen de convertir le type de données postgresql 9.3 afin qu'il n'affecte qu'un seul côté