Compartilhando uma única sequência de chave primária em um banco de dados?

14

É uma prática aceitável usar uma única sequência como chave primária em todas as tabelas (em vez de uma chave primária ser exclusiva para uma determinada tabela, é exclusiva para todas as tabelas)? Nesse caso, é objetivamente melhor do que usar uma única sequência de chave primária nas tabelas.

Sou desenvolvedor júnior de software, não DBA, por isso ainda estou aprendendo muitos conceitos básicos de bom design de banco de dados.

Edit: No caso de alguém estar se perguntando, li recentemente uma crítica de um design de banco de dados por um dos DBAs da nossa empresa que mencionou que era um problema o design não usar uma única chave primária em todo o banco de dados, que soava diferente do que Eu aprendi até agora.

Edit2: Para responder a uma pergunta nos comentários, isso é para o Oracle 11g, mas eu estava pensando em um nível não específico do banco de dados. Se essa pergunta depender do banco de dados, eu estaria interessado em saber o porquê, mas, nesse caso, estaria procurando uma resposta específica para o Oracle.

Lawtonfogle
fonte
2
Geralmente, é uma péssima idéia, por razões de desempenho.
Philᵀᴹ
1
Na verdade, há um benefício mais forte em ter cada tabela com seu próprio intervalo de chave primária independente. Mas somente quando você olha para um monte de IDs, pode-se dizer que este é Contas, que é Chefe de Compras, etc. Isso exige alguma configuração e (como qualquer finalidade especial) cuidados e alimentação contínuos. (Sim, eu trabalhei com um sistema como esse, há muitos anos.)
RLF
Qual DBMS você está usando? Oráculo? Postgres? DB2?
a_horse_with_no_name
1
É possível que você tenha interpretado mal o que ele quis dizer? Talvez ele não estivesse sendo tão literal?
JamesRyan
O DBA da empresa realmente quis dizer que não há campos de chave primária presentes em nenhuma das tabelas?
Max Vernon

Respostas:

13

Aceitável? Certo. Comum? Não. Benéfico? Duvidoso.

No meu antigo trabalho, herdamos um sistema em que eles tinham um gerador de seqüência central (este era um sistema SQL Server muito antes de SEQUENCEser introduzido no SQL Server 2012). Não era realmente um gargalo de desempenho e não deveria ser, a menos que você esteja gerando centenas de milhares de valores por segundo. Mas tornou todo o código muito mais complexo do que deveria ser, sem uma boa razão. A intenção do design era garantir que, se algo no sistema tivesse um valor de ID 12, apenas uma coisa no sistema poderia ter o ID 12. Isso me pareceu bastante obtuso e eu nunca o entendi. Se eu tenho um cliente com CustomerID = 12, por que isso me impede de fazer um pedido com OrderID = 12?

Eu vejo a utilidade de um gerador de sequência central se você tiver vários sistemas e estiver gerando IDs para um determinado tipo de entidade (por exemplo, um cliente ou um pedido) desses vários sistemas. Uma sequência central pode distribuir novos valores para vários sistemas sem ser um gargalo (apenas um ponto de falha) e sem medo de dois sistemas gerando o mesmo ID.

Aaron Bertrand
fonte
Se você tivesse que escolher entre algo assim e apenas usar identificadores únicos como chaves primárias, você teria uma preferência (embora a resposta provavelmente seja "depende")? Parece que um GUID contornaria o problema da mesma maneira, exceto que você obteria uma implementação padrão em vez de precisar rolar seu próprio gerador de chave primária centralizado. Obviamente, o uso de uma sequência no SQL 2012 realizaria as duas coisas, mas supondo que alguém esteja em uma versão mais antiga?
SqlRyan
2
@SqlRyan Eu precisaria entender por que um OrderID precisa ser completamente diferente de um CustomerID. Eu quase certamente não usaria um GUID para isso; a configuração dos intervalos de IDENTIDADE pode ser melhor (os clientes começam em 1, os pedidos começam em 1000000 etc.), com alertas para quando você chegar perto de esgotar o intervalo, é claro.
Aaron Bertrand
1
@SllRyan - usar um GUID mal implementado como chave primária em cluster pode causar todos os tipos de problemas. Como Aaron disse, a IDENTITY se encaixa muito melhor ao objetivo.
Max Vernon
Em um sistema anterior, eu vi usando uma única seqüência em todo o banco de dados, isso foi feito para permitir que uma chave estrangeira aponte para várias tabelas diferentes em vez de uma única tabela, de modo que quando você disse que a chave estrangeira de duas linhas diferentes eram 12, você sabia que eles apontavam para a mesma coisa sem precisar verificar para qual tabela possível eles apontavam. Um 13 na mesma coluna pode ser a chave primária em uma tabela diferente. Pessoalmente, estou muito desconfortável com esse estilo de design.
Lawtonfogle 27/09/13
@AaronBertrand Ou, como alternativa, use identificadores inteiros simples e acrescente algum código ao início quando eles estiverem voltados para o cliente. por exemplo. I1337, C1337 claramente uma factura ou cliente
JamesRyan
7

A ideia tem mérito em um banco de dados muito complexo, no qual as pessoas podem ingressar acidentalmente em uma tabela usando a coluna errada e obter linhas inválidas, apenas porque os IDs INT são os mesmos.

Optamos por ter GUIDs seqüenciais como nossas chaves primárias, a fim de evitar algumas das armadilhas de fragmentação de índice dos GUIDs. Infelizmente eles são bastante grandes.

O servidor SQL pode gerar GUIDs seqüenciais por padrão, invocando a função newSequentialID (), portanto, não há tabela de chaves emitidas para manter e nenhum gargalo de bloqueio.

Isso nos deu IDs únicos em todos os bancos de dados, em toda a empresa, na verdade, pois eles são realmente únicos.

O preço do curso é o espaço e é problemático quando você tenta transferir os dados para um Data Warehouse / Cube em que a velocidade / tamanho se baseia em usar chaves inteiras menores.

Estou convencido de que evitamos muitos bugs em nosso aplicativo como resultado do uso deles.

RayG
fonte
4

Não consigo imaginar qual seria o motivo por trás da sequência única em todas as tabelas. Tudo o que faz é criar um gargalo ao gerar novos valores.

Não importa quão pequena seja a sobrecarga de gerar valores-chave sequenciais, o gerador é um único recurso, cujo acesso deve ser sincronizado. Quanto mais solicitações, maiores as chances de alguns solicitantes aguardarem sua vez na torneira. É óbvio que o gerador de sequência única compartilhado entre todas as tabelas será acessado com mais frequência por mais clientes, produzindo mais contenção do que qualquer um dos vários geradores. A disputa pode se tornar mais pronunciada se as regras de negócios impuserem restrições aos valores gerados, como ausência de lacunas ou ordem estrita, ou em um banco de dados em cluster.

Mesmo com o gerador de seqüência mais eficiente, haverá uma carga de trabalho que causa contenção intolerável.

mustaccio
fonte
2
Você pode adicionar detalhes sobre como o gargalo é criado e por que essa é uma má ideia.
Max Vernon
2

o objetivo das tabelas PrimaryKey nas banco de dados é principalmente impor a exclusividade dos dados que deveriam ser exclusivos, porque todos os fluxos de trabalho não podem ser cobertos e garantidos que isso não resultará em duplicação de dados. A segunda razão é que, muitas vezes, o PK também é o candidato principal ao Índice agrupado na tabela, aumentando a recuperação de dados quando / onde essas colunas são usadas corretamente na consulta de seleção.

o uso de um número de sequência como chave primária é o mesmo que todas as tabelas possuem a coluna Identity e somente essa coluna está sendo usada na PrimaryKey. ter um número de sequência único no banco de dados deve ter algum uso específico, mas, do ponto de vista da PrimaryKey, não entendo o motivo. por exemplo, em um projeto do Datawarehouse em que trabalhei, temos a coluna chamada LoadBatchID e do ETL para reportar que 50% de toda a tabela possui essa coluna, mas em alguns lugares tem um significado diferente. usamos o proc exclusivo como gerador de números para garantir que não encontremos conflitos e também nos ajudem a rastrear o arquivo original de onde os dados vieram e o que acontece em cada estágio diferente do ETL.

Anup Shah
fonte
2

Suponho que uma razão para fazê-lo seria se todas as entidades herdadas de alguma entidade pai. Digamos, por exemplo, que você queira colocar um comentário em qualquer tipo de entidade:

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

Geralmente isso não é feito. .

Não conheço as características de desempenho.

Neil McGuigan
fonte