É uma prática ruim ter vários relacionamentos individuais mutuamente exclusivos?


38

Digamos, uma tabela cartem relacionamento um-para-um para tabelas electric_car, gas_care hybrid_car. Se a carfor electric_car, ele não poderá mais aparecer em gas_carou a hybrid_car, etc.

Há algo de errado com esse design? Alguns problemas que podem ocorrer no caminho?

Respostas:


59

Os diferentes tipos de carros são uma instância de um problema geral que surge repetidamente na modelagem de dados. É chamado de "generalização / especialização" na modelagem de ER e "superclasse / subclasse" na modelagem de objetos.

Um modelador de objetos usa os recursos de herança criados no modelo de objetos para resolver o problema com bastante facilidade. As subclasses simplesmente estendem a superclasse.

O modelador relacional enfrenta um problema. como projetar as tabelas para simular os benefícios que se obteria da herança?

A técnica mais simples é chamada herança de tabela única . Os dados sobre todos os tipos de carros são agrupados em uma única tabela para carros. Há uma coluna, car_type, que agrupa todos os carros de um único tipo. Nenhum carro pode pertencer a mais de um tipo. Se uma coluna for irrelevante para, digamos, carros elétricos, ela ficará NULL nas linhas que pertencem a carros elétricos.

Esta solução simples funciona bem para os casos menores e mais simples. A presença de muitos NULLs adiciona um pouco à sobrecarga de armazenamento e um pouco à sobrecarga de recuperação. O desenvolvedor pode precisar aprender a lógica de três valores do SQL se testes booleanos forem feitos em colunas anuláveis. Isso pode ser desconcertante no começo, mas a gente se acostuma.

Existe outra técnica, chamada herança da tabela de classes . Nesse design, existem tabelas separadas para gas_car, electric_car e hybrid_car, além de uma tabela combinada, car, para todas elas. Quando você deseja todos os dados sobre um tipo específico de carro, associa-se à tabela de carros com a tabela especializada apropriada. Existem menos NULLs nesse design, mas você faz mais junções. Essa técnica funciona melhor nos casos maiores e mais complexos.

Existe uma terceira técnica chamada chave primária compartilhada. Essa técnica é frequentemente usada em conjunto com a herança da tabela de classes. As tabelas especializadas para as subclasses têm como chave primária uma cópia da chave primária da entrada correspondente na tabela car. Essa coluna de ID pode ser declarada como a chave primária e uma chave estrangeira.

Isso envolve um pouco de programação extra quando novos carros devem ser adicionados, mas torna as junções simples, fáceis e rápidas.

Superclasses e subclasses acontecem o tempo todo no mundo real. Não tenha medo. Mas teste seu design inicial para desempenho. Se a sua primeira tentativa for simples e sólida, você poderá ajustá-la para acelerar.


3
Uau, obrigado! Isso é o que eu estava tentando descobrir. A herança da tabela de classes parece ser exatamente o que eu preciso. Alterei minha resposta aceita para futuros leitores, pois acho que cobre completamente a questão, não apenas o meu caso.
Arthur Tarasov

6
Excelente resposta aqui. Uma dica: documente completamente essas decisões de design. Qualquer que seja o caminho a seguir, não será óbvio quando alguém estiver examinando a estrutura do banco de dados. Alguns bancos de dados, como o Postgres, permitem vincular um comentário juntamente com os metadados de suas colunas, tabelas e outros.
Basil Bourque

Você não trata da restrição de impedir que carros elétricos também sejam carros híbridos. Você precisa de uma tabela separada para isso.
jmoreno

2
Você está certo. Se você adicionar um campo car_type à tabela cars, poderá limitar os carros a pertencerem a apenas um tipo, à custa de desviar-se da normalização total. Um bom DBMS permitirá definir uma restrição de verificação que impedirá a entrada de um carro em mais de uma tabela especializada. Há alguma sobrecarga nisso, você adiciona carros novos.
precisa

@WalterMitty, mas sem um car_typecampo, como você saberia qual tabela procurar detalhes ao recuperar dados? Você precisa ler todas as três tabelas para ver qual delas possui dados sobre esse carregistro específico ?
Josh Parte

12

Não há nada errado em ter tantos subtipos de entidades em seu modelo quanto necessário para refletir a realidade dos dados que você está tentando modelar. A questão não é se os subtipos são uma má prática. A questão pode ser: é um bom modelo ?

Por exemplo, no seu exemplo, o que você faz com algo como um Audi A4 eTron - que é um híbrido plug-in? É um "carro elétrico" ou é um "carro híbrido"?

A outra pergunta que você deve se perguntar é por que está digitando alguma coisa? Quantos predicados distintos você tem nos seus subtipos? Algum desses predicados é compartilhado entre subtipos? A situação pode ficar complicada.

Sub-digitação não é usada no design do banco de dados para classificação. Você pode fazer a classificação com códigos, chaves estrangeiras para tabelas de códigos ou com sinalizadores. A sub-digitação é usada para modelar conjuntos de predicados distintos para diferentes tipos de interesse. Se você estiver usando subtipos apenas para classificação, é uma prática ruim.

Se seus subtipos modelam clara e inequivocamente conjuntos de predicados diferentes para as coisas com as quais seu banco de dados se importa, é uma prática perfeitamente boa, independentemente de quantos subtipos você precisar.


Obrigado, eu tinha medo de estar montando uma espécie de armadilha para mim. Meu problema é que cada um dos subtipos terá muitas colunas. Alguns irão se sobrepor e eu os colocarei em uma cartabela, mas muitos não serão e serão colocados em uma tabela de subtipos. Por exemplo, será como armazenar partes elementares de tipos de carros. O motor do carro elétrico pode ter 100 peças, o motor a gás 75 peças e o híbrido 125 peças. 50 partes seria comum e armazenados em cars, enquanto 50, 25 e 75 estarão em electric_car, gas_care hybrid_carmesas
Arthur Tarasov
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.