Digamos que uma tabela car
tenha um relacionamento um para um com tabelas electric_car
, gas_car
e hybrid_car
. Se a car
for electric_car
, não poderá mais aparecer em gas_car
ou a hybrid_car
, etc.
Há algo de errado com esse design? Alguns problemas que podem ocorrer no caminho?
Os diferentes tipos de carros são um exemplo de um problema geral que aparece repetidamente na modelagem de dados. É chamado de "generalização/especialização" na modelagem ER e "superclasse/subclasse" na modelagem de objetos.
Um modelador de objetos usa os recursos de herança embutidos no modelo de objeto para resolver o problema com bastante facilidade. As subclasses simplesmente estendem a superclasse.
O modelador relacional se depara com um problema. como projetar as tabelas de modo a emular os benefícios que se obteria da herança?
A técnica mais simples é chamada de herança de tabela única . Os dados sobre todos os tipos de carros são agrupados em uma única tabela para carros. Existe 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 será deixada 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 ter que aprender a lógica de três valores SQL se os testes booleanos forem feitos em colunas anuláveis. Isso pode ser desconcertante no começo, mas a pessoa se acostuma.
Existe outra técnica, chamada herança de tabela de classe . Nesse design, existem tabelas separadas para gas_car, electric_car e hybrid_car, além de uma tabela combinada, car, para todos eles. Quando você deseja todos os dados sobre um tipo específico de carro, você une a tabela de carros com a tabela especializada apropriada. Há menos NULLs neste design, mas você faz mais associações. Esta 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 herança de tabela de classe. As tabelas especializadas para as subclasses têm como chave primária uma cópia da chave primária da entrada correspondente na tabela carro. Essa coluna id pode ser declarada como chave primária e 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 quanto ao desempenho. Se sua primeira tentativa for simples e sólida, você poderá ajustá-la para acelerá-la.
Não há nada de errado em ter tantos subtipos de entidade em seu modelo quantos forem necessários para refletir a realidade dos dados que você está tentando modelar. A questão não é se os subtipos são uma prática ruim. O problema 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? Isso é um "carro elétrico" ou é um "carro híbrido"?
A outra pergunta que você deve se perguntar é por que você está subdigitando? Quantos predicados distintos você tem em seus subtipos? Algum desses predicados é compartilhado entre subtipos? A situação pode se complicar.
A subdigitação não é usada no design de 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 subtipagem é usada para modelar conjuntos de predicados distintos para diferentes tipos de algo de interesse. Se você estiver usando subtipos apenas para classificação, isso é uma prática ruim.
Se seus subtipos modelam de forma clara e inequívoca diferentes conjuntos de predicados para as coisas com as quais seu banco de dados se preocupa, então é uma prática perfeitamente boa, independentemente de quantos subtipos você precisa.