Por que você indexaria text_pattern_ops em uma coluna de texto?

18

Hoje, sete bancos de dados em sete semanas me apresentaram os índices por operador.

Você pode indexar seqüências de caracteres para o padrão que corresponde às consultas anteriores, criando um text_pattern_opsíndice de classe do operador, desde que os valores sejam indexados em minúsculas.

CREATE INDEX moves_title_pattern ON movies (
    (lower(title) text_pattern_ops);

Usamos o text_pattern_opsporque o título é do tipo texto. Se você precisar índice VARCHAR, caracteres, ou nomes, use os ops relacionados: varchar_pattern_ops, bpchar_pattern_ops, e name_pattern_ops.

Acho o exemplo realmente confuso. Por que é útil fazer isso?

Se a coluna for do tipo texto, os outros tipos (varchar, char, name) não serão convertidos em texto antes de serem usados ​​como um valor de pesquisa?

Como esse índice se comporta de maneira diferente de um usando o operador padrão?

CREATE INDEX moves_title_pattern ON movies (lower(title));
Iain Samuel McLean Elder
fonte
11
Esta questão relacionada pode ser útil
Erwin Brandstetter
Obrigado, Erwin. Sua resposta a essa pergunta foi muito útil ao pesquisar as idéias do livro.
Iain Samuel McLean Elder

Respostas:

20

A documentação geralmente fornece uma resposta para essas perguntas. Como também neste caso :

As classes de operador text_pattern_ops, varchar_pattern_ops e bpchar_pattern_ops suportam índices da árvore B nos tipos text, varchar e char, respectivamente. A diferença das classes de operadores padrão é que os valores são comparados estritamente caractere por caractere, e não de acordo com as regras de intercalação específicas do código do idioma. Isso torna essas classes de operadores adequadas para uso por consultas que envolvem expressões de correspondência de padrões (expressões regulares LIKE ou POSIX) quando o banco de dados não usa o código de idioma "C" padrão. Como exemplo, você pode indexar uma coluna varchar como esta:

CREATE INDEX test_index ON test_table (col varchar_pattern_ops);

Observe que você também deve criar um índice com a classe de operador padrão se desejar que consultas que envolvam comparações comuns <, <=,> ou> = usem um índice. Essas consultas não podem usar as classes de operador xxx_pattern_ops . (Porém, comparações comuns de igualdade podem usar essas classes de operadores.) É possível criar vários índices na mesma coluna com diferentes classes de operadores.

A documentação continua dizendo:

Se você usar o código de idioma C, não precisará das classes de operador xxx_pattern_ops, porque um índice com a classe de operador padrão é utilizável para consultas de correspondência de padrões no código de idioma C.

Você pode verificar seu código do idioma da seguinte maneira (é provável que seja UTF8 em vez de "C"):

postgres=> show lc_collate;
 lc_collate
-------------
 en_GB.UTF-8
dezso
fonte
Aha! Eu li isso, mas achei difícil seguir, então não entendi. Você diria que a utilidade útil de text_pattern_opsdepende da localidade? Parece que me beneficiaria porque meu código de idioma é 'en_US.UTF-8' (não 'C'), portanto, as consultas padrão não podem usar o índice padrão.
Iain Samuel McLean Elder
Exatamente. Eu acrescentaria (mas isso é apenas especulação) que, com os dados permanecendo dentro dos caracteres ASCII básicos, a classe de operador padrão é tão boa - pelo menos eu vejo consultas com LIKE 'something%' usando esses índices.
Dezso
5
@dezso: Se você viu uma LIKEconsulta usando um índice b-tree simples, o banco de dados deve estar usando o Ccódigo de idioma. Ou o índice é definido com o COLLATE "POSIX"(ou COLLATE "C") e a consulta especifica uma correspondência COLLATION. Com qualquer outro agrupamento, a ordem do índice não corresponde às regras de localidade e, portanto, não pode ser usada para correspondência de padrões.
Erwin Brandstetter
11
@ ErwinBrandstetter Tenho que confirmar, você está certo.
Dezso
11
@StopHarmingMonica você obtém a resposta correta (e nenhum erro), apenas a consulta será possivelmente mais lenta, não podendo usar o índice.
dezso 11/11