Variante IMUTÁVEL de unaccent()
Para esclarecer a desinformação na atualmente aceita, resposta incorreta :
Os índices de expressão permitem apenas
IMMUTABLE
funções (por razões óbvias) e unaccent()
é apenas STABLE
. A solução que você sugeriu no comentário também é problemático. Explicação detalhada e uma solução adequada para isso :Dependendo do conteúdo de
tags->name
pode ser útil adicionar unaccent()
ao índice de expressão, mas isso é ortogonal à pergunta por que o índice não estava sendo usado:Problema/solução real
O operador
LIKE
em sua consulta está sutilmente errado (provavelmente). Você não quiser interpretar 'Weststrasse' como padrão de pesquisa, você deseja corresponder à string (normalizada) como está. Substitua pelo =
operador, e você verá uma varredura de índice (bitmap) com seu índice atual, independente da volatilidade da função de unaccent()
:SELECT * FROM germany.ways
WHERE lower(tags->'name') = lower(unaccent('unaccent','Weststrasse'))
Por quê?
O operando direito de
LIKE
é um padrão . O Postgres não pode usar um índice btree simples para correspondência de padrões ( exceções se aplicam
). Um LIKE
com uma string simples como padrão (sem caracteres especiais) pode ser otimizada com uma verificação de igualdade no índice btree. Mas se houver caracteres especiais na string, este índice está fora. Se houver um
IMMUTABLE
função à direita de LIKE
, ele pode ser avaliado imediatamente e a referida otimização ainda é possível. De acordo com a documentação sobre Categorias de volatilidade de função
:O mesmo não é possível com uma menor volatilidade de função (
STABLE
ou VOLATILE
). É por isso que sua "solução" de fingir um IMMUTABLE unaccent()
parecia funcionar, mas é realmente colocar batom em um porco. Reiterar:
- Se você quiser trabalhar com
LIKE
e padrões, use um índice de trigrama . - Se você não quiser trabalhar com
LIKE
e padrões, use o operador de igualdade=