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:
pg_trgm
você precisa de uma string de consulta de pelo menos 3 caracteres de comprimento, por exemplofo%
, não acertaria o índice, mas faria uma varredura. Algo a ser observado.Possivelmente os mais rápidos são padrões ancorados com distinção entre maiúsculas e minúsculas, como os que podem usar índices. ou seja, não há curinga no início da string de correspondência, então o executor pode usar uma varredura de faixa de índice. ( o comentário relevante nos documentos está aqui ) Lower e ilike também perderão sua capacidade de usar o índice, a menos que você crie um índice especificamente para esse propósito (consulte índices funcionais ).
Se você deseja pesquisar uma string no meio do campo, deve examinar os índices de texto completo ou trigrama . O primeiro deles está no núcleo do Postgres, o outro está disponível nos módulos contrib.
fonte
Você pode instalar o Wildspeed , um tipo diferente de índice no PostgreSQL. Wildspeed funciona com curingas% word%, sem problemas. A desvantagem é o tamanho do índice, pode ser grande, muito grande.
fonte
Execute a consulta mencionada abaixo para melhorar o desempenho da consulta LIKE no postgresql. crie um índice como este para tabelas maiores:
fonte
pelo que vale a pena, Django ORM tende a usar
UPPER(text)
para todas asLIKE
consultas para torná-lo insensível a maiúsculas,Adicionar um índice
UPPER(column::text)
acelerou muito meu sistema, ao contrário de qualquer outra coisa.Quanto a% principal, sim isso não vai usar um índice. Veja este blog para uma ótima explicação:
https://use-the-index-luke.com/sql/where-clause/searching-for-ranges/like-performance-tuning
fonte
Recentemente, tive um problema semelhante com uma tabela contendo 200.000 registros e preciso fazer consultas LIKE repetidas. No meu caso, a string que está sendo pesquisada foi corrigida. Outros campos variaram. Por isso, fui capaz de reescrever:
Como
Fiquei encantado quando as consultas voltaram rapidamente e verifiquei se o índice está sendo usado com
EXPLAIN ANALYZE
:fonte
Suas consultas semelhantes provavelmente não podem usar os índices que você criou porque:
1) seus critérios LIKE começam com um curinga.
2) você usou uma função com seus critérios LIKE.
fonte
Sempre que você usar uma cláusula em uma coluna com funções, por exemplo, LIKE, ILIKE, superior, inferior, etc. Então o postgres não levará seu índice normal em consideração. Ele fará uma varredura completa da tabela passando por cada linha e, portanto, será lento.
A maneira correta seria criar um novo índice de acordo com sua consulta. Por exemplo, se eu quiser corresponder a uma coluna sem distinção entre maiúsculas e minúsculas e minha coluna é um varchar. Então você pode fazer assim.
Da mesma forma, se a sua coluna for um texto, você faz algo assim
Da mesma forma, você pode alterar a função superior para qualquer outra função que desejar.
fonte