比方说,一个表car
有一个一对一关系的表electric_car
,gas_car
和hybrid_car
。如果a car
为electric_car
,则不能再出现在gas_car
或中hybrid_car
,等等。
这样的设计有什么问题吗?将来可能会出现一些问题?
比方说,一个表car
有一个一对一关系的表electric_car
,gas_car
和hybrid_car
。如果a car
为electric_car
,则不能再出现在gas_car
或中hybrid_car
,等等。
这样的设计有什么问题吗?将来可能会出现一些问题?
Answers:
不同类型的汽车是一个普遍问题的实例,该问题在数据建模中一遍又一遍地浮出水面。在ER建模中称为“一般化/专业化”,在对象建模中称为“超类/子类”。
对象建模器使用对象模型中内置的继承功能来轻松解决问题。子类只是扩展超类。
关系建模者面临一个问题。如何设计表以模仿继承带来的好处?
最简单的技术称为单表继承。有关所有类型汽车的数据被分组到一个汽车表中。有一个列car_type,将一个类型的所有汽车组合在一起。汽车不能属于一种以上的类型。如果某列与电动汽车无关,则在与电动汽车有关的行中将其保留为NULL。
这种简单的解决方案适用于较小和较简单的情况。大量NULL的存在会增加一点存储开销,并增加一些检索开销。如果对可空列进行布尔测试,则开发人员可能必须学习SQL三值逻辑。一开始这可能令人困惑,但是一个人已经习惯了。
还有另一种技术,称为类表继承。在此设计中,除了用于所有表的合并表car之外,还有用于gas_car,electric_car和hybrid_car的单独表。当您需要有关特定类型汽车的所有数据时,可以将汽车表与适当的专用表结合在一起。此设计中的NULL较少,但是您进行的连接更多。在较大和更复杂的情况下,此技术效果更好。
第三种技术称为共享主键。此技术通常与类表继承结合使用。子类的专用表具有car表中相应条目的主键副本作为其主键。可以将此id列声明为主键和外键。
当要添加新车时,这涉及一些额外的编程,但是这使连接变得简单,容易和快速。
超级类和子类在现实世界中始终存在。不要害怕 但是请测试您的初始设计的性能。如果您的第一次尝试既简单又合理,则可以对其进行调整以加快速度。
car_type
字段,检索数据时您如何知道要在哪个表中查找详细信息?您是否必须阅读所有三个表以查看哪个表具有有关该特定car
记录的数据?
在模型中拥有足够多的实体子类型以反映您要建模的数据的真实性并没有错。问题不是子类型是否是一种不好的做法。问题可能是它是一个好的模型吗?
例如,在您的示例中,您如何使用奥迪A4 eTron等插电式混合动力车?这是“电动汽车”还是“混合动力汽车”?
您还必须问自己的另一个问题是,为什么您根本要分型?您的子类型中有多少个不同的谓词?这些谓词是否在子类型之间共享?情况可能变得复杂。
数据库设计中未使用子类型进行分类。您可以使用代码,代码表的外键或标志进行分类。子类型用于为不同类型的关注事物建模不同的谓词集。如果您仅将子类型用于分类,那么这是一个不好的做法。
如果您的子类型清楚明确地为数据库关心的事物建模不同的谓词集,那么这是一个很好的实践,无论您需要多少个子类型。
car
表中,但是很多不会,并且会放在子类型表中。例如,它将类似于存储汽车类型的基本部件。电动汽车发动机可以有100份,汽油汽车发动机有75份,混合动力有125份。50份将是常见的,并存储在cars
,而50,25和75将在electric_car
,gas_car
和hybrid_car
表