Pelo que pude entender a documentação, as seguintes definições são equivalentes:
create table foo (
id serial primary key,
code integer,
label text,
constraint foo_uq unique (code, label));
create table foo (
id serial primary key,
code integer,
label text);
create unique index foo_idx on foo using btree (code, label);
No entanto, uma observação no manual do Postgres 9.4 diz:
A maneira preferida de adicionar uma restrição exclusiva a uma tabela é
ALTER TABLE ... ADD CONSTRAINT
. O uso de índices para impor restrições exclusivas pode ser considerado um detalhe de implementação que não deve ser acessado diretamente.
(Editar: esta nota foi removida do manual com o Postgres 9.5.)
É apenas uma questão de bom estilo? Quais são as consequências práticas da escolha de uma dessas variantes (por exemplo, no desempenho)?
sql
postgresql
unique
Adam Piotrowski
fonte
fonte
Respostas:
Eu tinha algumas dúvidas sobre esse problema básico, mas importante, então decidi aprender pelo exemplo.
Vamos criar o mestre da tabela de teste com duas colunas, con_id com restrição exclusiva e ind_id indexado por índice exclusivo.
Na descrição da tabela (\ d em psql), você pode distinguir a restrição exclusiva do índice exclusivo.
Singularidade
Vamos verificar a exclusividade, apenas por precaução.
Funciona como esperado!
Chaves estrangeiras
Agora vamos definir a tabela de detalhes com duas chaves estrangeiras referenciando nossas duas colunas no mestre .
Bem, sem erros. Vamos garantir que funcione.
Ambas as colunas podem ser referenciadas em chaves estrangeiras.
Restrição usando índice
Você pode adicionar restrições de tabela usando o índice exclusivo existente.
Agora não há diferença entre a descrição das restrições da coluna.
Índices parciais
Na declaração de restrição de tabela, você não pode criar índices parciais. Vem diretamente da definição de
create table ...
. Na declaração de índice exclusivo, você pode definirWHERE clause
para criar um índice parcial. Você também pode criar um índice na expressão (não apenas na coluna) e definir alguns outros parâmetros (agrupamento, ordem de classificação, posicionamento de NULLs).Você não pode adicionar restrição de tabela usando índice parcial.
fonte
Mais uma vantagem de usar
UNIQUE INDEX
vs.UNIQUE CONSTRAINT
é que você pode facilmenteDROP
/CREATE
um índiceCONCURRENTLY
, enquanto que com uma restrição não pode.fonte
O texto completo
Portanto, o desempenho da velocidade deve ser o mesmo
fonte
Outra coisa que encontrei é que você pode usar expressões sql em índices exclusivos, mas não em restrições.
Portanto, isso não funciona:
mas seguindo obras.
fonte
citext
extensão.Como várias pessoas forneceram vantagens de índices exclusivos sobre restrições exclusivas, aqui está uma desvantagem: uma restrição exclusiva pode ser adiada (verificada apenas no final da transação), um índice exclusivo não pode ser.
fonte
Eu li isso no documento:
Então, eu acho que é o que você chama de "exclusividade parcial", adicionando uma restrição.
E, sobre como garantir a exclusividade:
Portanto, devemos adicionar restrições, o que cria um índice, para garantir a exclusividade.
Como vejo esse problema?
Uma "restrição" visa garantir gramaticalmente que esta coluna seja única, estabelece uma lei, uma regra; enquanto "índice" é semântico , sobre "como implementar, como alcançar a exclusividade, o que significa único quando se trata de implementação". Portanto, a maneira como o Postgresql a implementa é muito lógica: primeiro, você declara que uma coluna deve ser única; depois, o Postgresql adiciona a implementação da adição de um índice exclusivo para você .
fonte
where
cláusula, para que você possa definir que os registros sejam IFF exclusivos e atendam a alguns critérios. Isso simplesmente desativa as restrições de um conjunto indefinido de registros que antecedem a restrição que está sendo criada. É completamente diferente, e o último é significativamente menos útil, embora seja conveniente para migrações progressivas, eu acho.Há uma diferença no bloqueio.
A adição de um índice não bloqueia o acesso de leitura à tabela.
A adição de uma restrição coloca um bloqueio de tabela (para que todas as seleções sejam bloqueadas), uma vez que é adicionado via ALTER TABLE .
fonte
Uma coisa muito pequena que pode ser feita apenas com restrições e não com índices está usando a
ON CONFLICT ON CONSTRAINT
cláusula ( consulte também esta pergunta ).Isso não funciona:
Produz:
Transforme o índice em uma restrição:
E a
INSERT
declaração agora funciona.fonte