Os documentos do Postgres dizem:
O uso de índices para impor restrições exclusivas pode ser considerado um detalhe de implementação que não deve ser acessado diretamente. Deve-se, no entanto, estar ciente de que não há necessidade de criar índices manualmente em colunas únicas; fazer isso apenas duplicaria o índice criado automaticamente.
Com base nisso, se eu quiser um índice de expressão em uma coluna e também quiser que essa coluna seja única, case 2
abaixo seria melhor, pois pode realizar o acima com um único índice. Considerando case 1
que teria um índice criado automaticamente por causa de uma restrição única e outro porque preciso de um índice em minúsculas?
Como @Colin'tHart apontou, esses 2 casos não são os mesmos. Eu deveria ter postado esta pergunta sem o uso de lower()
expressão. Nesse caso, entendo que a CREATE UNIQUE INDEX
seria melhor do que uma restrição única e um índice simples.
Com base nisso, se eu quiser um índice com uma classe de operador (por exemplo text_pattern_ops
, ) em uma coluna e também quiser que essa coluna seja única, case 2
abaixo seria melhor, pois pode realizar o acima com um único índice. Considerando case 1
que teria um índice criado automaticamente por causa de uma restrição única e outro porque preciso de uma classe de operador diferente?
Caso 1:
CREATE TABLE book (
id SERIAL PRIMARY KEY,
name text NOT NULL,
CONSTRAINT book_name_key UNIQUE (name)
);
CREATE INDEX book_name_like ON book (name text_pattern_ops);
Caso 2:
CREATE TABLE book (
id SERIAL PRIMARY KEY,
name text NOT NULL
);
CREATE UNIQUE INDEX book_name_like ON book (name text_pattern_ops);
Por um momento, pensei que alguém poderia usar um
text_pattern_ops
índice pré-existente com aUSING INDEX
cláusula ao adicionar um arquivoUNIQUE CONSTRAINT
. Mas isso falha, porque:O manual:
Por exemplo, um índice exclusivo como esse permitiria uma restrição FK referenciando-o, mas teria um desempenho terrível , porque não oferece suporte a operadores padrão.
O manual:
Então, para responder à pergunta:
Se você precisar de um
UNIQUE CONSTRAINT
(entre outros motivos: para fazer referência a um FK), sua primeira variante com restrição e índice é a única opção. Além disso, a classe de operador padrão do índice criado pela restrição oferece suporte a mais operações (como classificação na ordem de classificação padrão).Se você não precisa de nada disso, vá com sua segunda variante porque, obviamente, apenas um índice é mais barato de manter: apenas um
UNIQUE text_pattern_ops
índice.Diferenças entre índice e restrição:
Alternativa com COLLATE "C"
Em vez de criar dois índices, há outra alternativa para índices que pode ser preferível. O manual:
xxx
_pattern_ops
E:
Você pode criar a coluna sem collation (usando
COLLATE "C"
). Em seguida, a classe de operador padrão se comporta da mesma maneiratext_pattern_ops
- além disso, o índice pode ser usado com todos os operadores padrão.Agora,
LIKE
pode usar o índice:Mas
ILIKE
ainda não pode:db<>fiddle aqui Old sqlfddle
Considere um índice de trigrama usando o módulo adicional pg_trgm para uma solução mais geral:
Tome cuidado.
Seus dois projetos não são os mesmos.
O caso 1 implementa uma restrição única no nome do livro, mas inclui maiúsculas e minúsculas, portanto, "O senhor das moscas" e "o senhor das moscas" seriam diferentes. O caso 1 então cria um segundo índice para dar suporte à pesquisa eficiente de consultas do formulário
O caso 2 é diferente. Ele força os títulos de seus livros a serem diferentes, independentemente de maiúsculas e minúsculas, e não permite que ambos os títulos acima sejam inseridos.