PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Variações de desempenho de consulta PostgreSQL LIKE

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, ele tem seus próprios operadores e não funciona para strings arbitrárias. Ele opera em palavras baseado em dicionários e lematização. Ele faz suporta correspondência de prefixo para palavras , mas não com o LIKE operador:
  • Obter correspondência parcial da coluna TSVECTOR indexada por GIN

Índices de trigramas para LIKE


Instale o módulo adicional pg_trgm que fornece classes de operadores para índices de trigramas GIN e GiST para suportar todos os LIKE e ILIKE padrões , 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);
  • Diferença entre o índice GiST e GIN

Exemplo de consulta:
SELECT * FROM tbl WHERE col LIKE '%foo%';   -- leading wildcard
SELECT * FROM tbl WHERE col ILIKE '%foo%';  -- works case insensitively as well

Trigramas? E as 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 prefixado ao determinar o conjunto de trigramas contidos na string.

E padrões de pesquisa com menos de 3 letras? O manual:

Para ambos LIKE e pesquisas de expressão regular, lembre-se de que um padrão sem trigramas extraíveis degenerará em uma varredura de índice completo.

Ou seja, as verificações de índice / bitmap de índice ainda funcionam (os planos de consulta para a instrução preparada não serão interrompidos), apenas não comprarão melhor desempenho. Normalmente, nenhuma grande perda, já que strings de 1 ou 2 letras dificilmente são seletivas (mais do que alguns por cento das correspondências de tabela subjacentes) e o suporte a í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


Apenas para ancorados à esquerda padrões (sem curinga inicial) você obtém o melhor com uma classe de operador adequada para um índice btree:text_pattern_ops ou varchar_pattern_ops . Ambos os recursos internos do Postgres padrão, sem necessidade de módulo adicional. Desempenho semelhante, mas índice muito menor.

Índice de exemplo:
CREATE INDEX tbl_col_text_pattern_ops_idx ON tbl(col text_pattern_ops);

Exemplo de consulta:
SELECT * FROM tbl WHERE col LIKE 'foo%';  -- no leading wildcard

Ou , se você deve executar seu banco de dados com o 'C' localidade (efetivamente não locale), 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 nestas respostas relacionadas no dba.SE:
  • Correspondência de padrões com LIKE, SIMILAR TO ou expressões regulares no PostgreSQL
  • Como o LIKE é implementado?
  • Encontrando strings semelhantes com o PostgreSQL rapidamente