比如说,一个表与表、和car
具有一对一的关系。如果 a是,它就不能再出现在or a等中。electric_car
gas_car
hybrid_car
car
electric_car
gas_car
hybrid_car
这样的设计有什么问题吗?未来可能会出现的一些问题?
比如说,一个表与表、和car
具有一对一的关系。如果 a是,它就不能再出现在or a等中。electric_car
gas_car
hybrid_car
car
electric_car
gas_car
hybrid_car
这样的设计有什么问题吗?未来可能会出现的一些问题?
不同类型的汽车是数据建模中反复出现的一般问题的一个实例。它在 ER 建模中称为“泛化/专业化”,在对象建模中称为“超类/子类”。
对象建模器使用对象模型中内置的继承特性来很容易地解决问题。子类只是扩展了超类。
关系建模器面临一个问题。如何设计表格以模拟从继承中获得的好处?
最简单的技术称为单表继承。有关所有类型汽车的数据都分组到一个汽车表中。有一列 car_type 将单一类型的所有汽车组合在一起。任何汽车都不能属于一种以上的类型。如果列与电动汽车无关,则在与电动汽车相关的行中将其保留为NULL。
这个简单的解决方案适用于更小和更简单的情况。大量 NULL 的存在增加了一点点存储开销和一点点检索开销。如果对可空列进行布尔测试,开发人员可能必须学习SQL 三值逻辑。起初这可能会令人困惑,但人们会习惯它。
还有另一种技术,称为类表继承。在此设计中,gas_car、electric_car 和 hybrid_car 有单独的表,此外还有一个组合表 car。当您想要有关特定类型汽车的所有数据时,您可以将汽车表与相应的专用表连接起来。此设计中的 NULL 较少,但您需要进行更多连接。这种技术在更大和更复杂的情况下效果更好。
第三种技术称为共享主键。这种技术通常与类表继承结合使用。子类的专用表具有 car 表中相应条目的主键的副本作为它们的主键。这个 id 列可以声明为主键和外键。
当要添加新车时,这涉及一些额外的编程,但它使连接变得简单、容易和快速。
超类和子类在现实世界中一直存在。不要害怕。但是一定要测试你的初始设计的性能。如果您的第一次尝试简单而合理,您将能够对其进行调整以加快速度。
在模型中拥有尽可能多的实体子类型以反映您尝试建模的数据的现实并没有错。问题不在于子类型是否是一种不好的做法。问题可能是它是一个好模型吗?
例如,在您的示例中,您如何处理像奥迪 A4 eTron 这样的插电式混合动力车?那是“电动汽车”还是“混合动力汽车”?
你必须问自己的另一个问题是,你为什么要分类型?您的子类型中有多少不同的谓词?这些谓词中的任何一个是否在子类型之间共享?情况可能会变得复杂。
子类型在数据库设计中不用于分类。您可以使用代码、代码表的外键或标志进行分类。子类型用于为不同类型的感兴趣事物建模不同的谓词集。如果您仅将子类型用于分类,那么这是一种不好的做法。
如果您的子类型为您的数据库所关心的事物清晰而明确地建模不同的谓词集,那么无论您需要多少子类型,这都是一个非常好的实践。