НЕИЗМЕНЕН вариант на unaccent()
За изясняване на дезинформацията в текущо приет, неправилен отговор
:
Индексите на изрази позволяват само IMMUTABLE
функции (по очевидни причини) и unaccent()
е само STABLE
. решението, което предложихте в коментара също е проблематично. Подробно обяснение и правилно решение за това :
В зависимост от съдържанието на tags->name
може да е полезно да добавите unaccent()
към индекса на израза, но това е ортогонално на въпроса защо индексът не е бил използван:
Действителен проблем/решение
Операторът LIKE
във вашата заявка е леко грешно (най-вероятно). Вие ненеправите искате да интерпретирате 'Weststrasse' като модел за търсене, искате да съвпаднете с (нормализирания) низ такъв, какъвто е. Заменете с =
оператор и ще видите сканиране на (растерен) индекс с текущия ви индекс, независимо на променливостта на функцията на unaccent()
:
SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Защо?
Десният операнд на LIKE
е модел . Postgres не може да използва обикновен btree индекс за съвпадение на шаблони ( важат изключения
). LIKE
с обикновен низ като шаблон (без специални знаци) може да се оптимизира с проверка за равенство на индекса btree. Но ако в низа има специални знаци, това индексът е изчерпан.
Ако има IMMUTABLE
функция отдясно на LIKE
, то може да бъде оценено незабавно и споменатата оптимизация все още е възможна. Според документация относно Категории променливост на функции
:
Същото не е възможно с по-малка волатилност на функцията (STABLE
или VOLATILE
). Ето защо вашето "решение" за фалшифициране на IMMUTABLE unaccent()
изглеждаше, че работи, но всъщност е да сложиш червило на прасе.
За да повторя:
- Ако искате да работите с
LIKE
и модели, използвайте триграмен индекссилен> . - Ако не искате да работите с
LIKE
и шаблони, използвайте оператора за равенство=