FTS não suporta LIKE
A resposta aceita anteriormente estava incorreta. A Pesquisa de Texto Completo com seus índices de texto completo não é para o LIKE
operador, ela tem seus próprios operadores e não funciona para strings arbitrárias. Ele opera em palavras com base em dicionários e lematização. Ele faz suporte prefixo correspondente de palavras , mas não com o LIKE
operador:
Índices trigramas para LIKE
Instale o módulo adicional pg_trgm
que fornece classes de operador para índices de trigrama GIN e GiST para suportar todos os padrões LIKE
eILIKE
, não apenas os ancorados à esquerda:
Índice de exemplo:
CREATE INDEX tbl_col_gin_trgm_idx ON tbl USING gin (col gin_trgm_ops);
Ou:
CREATE INDEX tbl_col_gist_trgm_idx ON tbl USING gist (col gist_trgm_ops);
Consulta de exemplo:
SELECT * FROM tbl WHERE col LIKE '%foo%'; -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%'; -- works case insensitively as well
Trigramas? E quanto a cordas mais curtas?
Palavras com menos de 3 letras em valores indexados ainda funcionam. O manual:
Cada palavra é considerada como tendo dois espaços prefixados e um espaço sufixado ao determinar o conjunto de trigramas contidos na string.
E os padrões de pesquisa com menos de 3 letras? O manual:
Para pesquisas LIKE
e expressões regulares, lembre-se de que um padrão sem trigramas extraíveis irá degenerar para uma varredura de índice completo.
Isso significa que as varreduras de índice / bitmap ainda funcionam (os planos de consulta para a instrução preparada não quebram), apenas não compram melhor desempenho. Normalmente sem grande perda, uma vez que cadeias de 1 ou 2 letras dificilmente são seletivas (mais do que alguns por cento das correspondências da tabela subjacente) e o suporte ao índice não melhoraria o desempenho para começar, porque uma varredura completa da tabela é mais rápida.
text_pattern_ops
para correspondência de prefixo
Para padrões ancorados apenas à esquerda (sem curinga inicial), você obtém o ótimo com uma classe de operadores adequada para um índice btree: text_pattern_ops
ou varchar_pattern_ops
. Ambos os recursos integrados do Postgres padrão, nenhum módulo adicional necessário. Desempenho semelhante, mas índice muito menor.
Índice de exemplo:
CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);
Consulta de exemplo:
SELECT * FROM tbl WHERE col LIKE 'foo%'; -- no leading wildcard
Ou , se você deveria estar executando seu banco de dados com a localidade 'C' (efetivamente sem localidade), então tudo é classificado de acordo com a ordem de bytes de qualquer maneira e um índice btree simples com classe de operador padrão faz o trabalho.
Mais detalhes, explicações, exemplos e links nessas respostas relacionadas no dba.SE: