PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Indeks GIN w kolumnie smallint[] nie jest używany lub operator błędu nie jest unikalny

Rozwiązanie

Najprawdopodobniej rozwiązanie jest zakwalifikowanie operatora do schematu:

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

Dlaczego?

Jest to problem rozdzielczości operatora (w połączeniu z rozdzielczością typu i kontekstem rzutowania).

W standardowym Postgresie istnieje tylko jeden operator kandydujący anyarray @>anyarray , właśnie tego chcesz.

Twoja konfiguracja działałaby dobrze, gdybyś nie zainstalował dodatkowego modułu intarray (moje założenie), który zapewnia inny operator dla integer[] @> integer[] .

Dlatego innym rozwiązaniem byłoby użycie integer[] zamiast tego i mieć indeks GIN z gin__int_ops klasa operatora. Lub wypróbuj (domyślnie dla intarray) gist__int_ops indeks. Oba mogą być szybsze, ale oba nie zezwalają na wartości NULL.
Lub możesz zmienić nazwę intarray operator @> ujednoznacznić. (Nie zrobiłbym tego. Pojawiają się problemy z aktualizacją i przenoszeniem).

Dla wyrażeń zawierających co najmniej jeden operand typu integer[] Postgres wie, który operator wybrać:operator intarray. Ale wtedy indeks nie ma zastosowania , ponieważ operator intarray działa tylko na integer (int4 ) nie int2 . A indeksy są ściśle powiązane z operatorami:

  • Czy PostgreSQL może indeksować kolumny tablicy?
  • Zachowanie PostgreSQL w obecności dwóch różnych typów indeksów w tej samej kolumnie

Ale dla int2[] @> int2[] , Postgres nie jest w stanie wybrać najlepszego operatora. Oba wydają się równie odpowiednie. Ponieważ domyślny operator znajduje się w pg_catalog schemat i operator intarray znajdują się w publicznie schemat (domyślnie - lub gdziekolwiek zainstalowałeś rozszerzenie), możesz pomóc rozwiązać zagadkę, kwalifikując operatora do schematu za pomocą OPERATOR() zbudować. Powiązane:

  • Porównaj tablice pod kątem równości, ignorując kolejność elementów

Otrzymany komunikat o błędzie jest nieco mylący. Ale jeśli przyjrzysz się uważnie, znajdziesz WSKAZÓWKA dodana linia, która podpowiada (tada!) we właściwym kierunku:

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.

Możesz zbadać istniejących kandydatów na operatora dla @> z:

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

Innym alternatywnym rozwiązaniem byłoby tymczasowe(!) ustawienie innej ścieżki_wyszukiwania, aby znaleźć tylko żądany operator. W tej samej transakcji:

SET LOCAL search_path = pg_catalog;
SELECT ...

Ale wtedy musisz zakwalifikować wszystkie tabele w zapytaniu według schematu.

Informacje o kontekście przesyłania:

  • Generuj serie dat — używając typu daty jako danych wejściowych

możesz zmień castcontext z int2 -> int4 . Ale zdecydowanie odradzam. Zbyt wiele możliwych skutków ubocznych:

  • Czy istnieje sposób na rzucenie typu danych postgresql 9.3, aby mógł wpływać tylko na jedną stronę?



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Instalacja Postgisa:typ geometria nie istnieje

  2. Wyjaśnij bardziej szczegółowo sugestię dotyczącą wydajności warunku JOIN vs. LEFT JOIN i WHERE

  3. Odpowiednik DATEADD w PostgreSQL

  4. lastInsertId nie działa w Postgresql

  5. Spłaszczyć zagregowane pary klucz/wartość z pola JSONB?