在 MySQL 中实现继承:备选方案和只有代理键的表

Posted

技术标签:

【中文标题】在 MySQL 中实现继承:备选方案和只有代理键的表【英文标题】:Implementing inheritance in MySQL: alternatives and a table with only surrogate keys 【发布时间】:2013-09-09 21:47:57 【问题描述】:

这个问题可能以前被问过,但我很难找到我的确切情况,所以我会解释我的情况以寻求一些反馈:

我有一个将注册位置的应用程序,我有几种类型的位置,每种位置类型都有一组不同的属性,但我需要将注释与位置相关联,而不管它们的类型和其他类型的内容(主要是多媒体条目和 cmets) 到所述注释。考虑到这一点,我想出了几个解决方案:

    为每个位置类型创建一个表,并为每个位置表使用外键创建一个“notes”表,这非常麻烦,因为我必须为每个 cmets 表创建一个多媒体和 cmets 表,例如:

    位置类型A

    身份证 属性1 属性2

    LocationTypeA_Notes

    身份证 属性1 ... Lo​​cationTypeA_fk

    LocationTypeA_Notes_Multimedia

    身份证 属性1 ... Lo​​cationTypeA_Notes_fk

    以此类推,这样做会很烦人,但是做完之后,在这种结构上开发应该不会那么麻烦。

    为位置创建一个具有唯一标识符的表,并将内容指向那里,如下所示:

    位置

    身份证

    位置类型A

    身份证 属性1 属性2 Lo​​cation_fk

    注意事项

    身份证 属性1 ... Lo​​cation_fk

    多媒体

    身份证 属性1 ... Notes_fk

    如您所见,这更简单,也更容易开发,但我只是不喜欢只有 ID 的表的外观(是的,这确实是我对此的唯一反对意见,这是我的选择老实说,最喜欢)。

    类似于选项 2,但我会有一个巨大的属性表,形状如下:

    位置

    身份证 类型

    属性

    姓名 价值

    等等,或者每个属性一个表;一个拉德鲁帕尔。这将是一个痛苦的开发,因为它需要几个插入/更新操作来在一个位置上做一些事情,并且属性表将比位置表大几倍(或者最终有大量的属性表);它也有代理键唯一表的相同问题(只是它现在有一个“类型”,我将使用它来以编程方式定义位置的行为),但这是一个很好的解决方案。

那么,对于这个问题:在性能和可扩展性方面,哪种解决方案的性能和可扩展性更好?您会选择哪种方案,或者您会提出哪些替代方案?我实现这些都没有问题,选项 2 和 3 将是一个有趣的发展,我从来没有做过这样的事情,但我不想选择在内容时会自行崩溃的选项增长一点;你可能在想“如果你知道 Drupal 的工作方式和你期望的一样,为什么不直接使用它?”,我在想“你显然不知道使用 Drupal 有多么困难,或者你是专家,我绝对不是”。

另外,既然我已经写了所有这些,您认为选项 2 总体上是个好主意吗?您知道分组实体/模拟继承的更好方法吗? (请不要说“只使用继承!”,我仅限于使用 mysql)。

感谢您的反馈,如果我写的太多而意思太少,我很抱歉。

【问题讨论】:

【参考方案1】:

ORM 系统通常使用以下解决方案,大部分与您在此处列出的解决方案相同:

每个层次结构一个表

优点:

简单的方法。 轻松添加新类,您只需为其他数据添加新列即可。 只需更改行的类型即可支持多态性。 数据访问速度很快,因为数据在一个表中。 即席报告非常简单,因为所有数据都可以在一个表中找到。

缺点:

类层次结构内的耦合增加了,因为所有类都直接耦合到同一个表。 一个类中的更改会影响表,然后会影响层次结构中的其他类。 数据库中可能会浪费空间。 当类型之间存在大量重叠时,指示类型变得复杂。 对于大型层次结构,表可以快速增长。

何时使用:

对于简单和/或浅层次的类层次结构来说,这是一个很好的策略,层次结构中的类型之间几乎没有重叠。

每个具体类一个表

优点:

易于进行临时报告,因为您需要的有关单个类的所有数据都仅存储在一个表中。 访问单个对象数据的性能良好。

缺点:

当您修改一个类时,您需要修改它的表以及它的任何子类的表。例如,如果您要向 Person 类添加身高和体重,则需要向 Customer、Employee 和 Executive 表添加列。 每当对象更改其角色时,也许您雇用了一位客户,您需要将数据复制到适当的表中并为其分配一个新的 POID 值(或者您可以重用现有的 POID 值)。 很难支持多个角色并仍然保持数据完整性。例如,您会在哪里存储既是客户又是员工的人的姓名?

何时使用:

当更改类型和/或类型之间的重叠很少见时。

每个班级一张桌子

优点:

由于一对一的映射,易于理解。 很好地支持多态性,因为您只需在每种类型的相应表中都有记录。 很容易修改超类和添加新的子类,因为您只需要修改/添加一个表。 数据大小的增长与对象数量的增长成正比。

缺点:

数据库中有很多表,每个类一个(加上表来维护关系)。 使用此技术读取和写入数据可能需要更长的时间,因为您需要访问多个表。如果您通过将每个表放在不同物理磁盘驱动器盘片上的类层次结构中来智能地组织数据库,则可以缓解此问题(假设磁盘驱动器磁头都独立运行)。 很难对数据库进行临时报告,除非您添加视图来模拟所需的表。

何时使用:

当类型之间存在显着重叠或经常更改类型时。

通用架构

优点:

当数据库访问被一个强大的持久性框架封装时,效果非常好。 可以扩展它以提供元数据以支持广泛的映射,包括关系映射。简而言之,它是映射元数据引擎的开始。 它非常灵活,使您能够快速更改存储对象的方式,因为您只需要相应地更新存储在 Class、Inheritance、Attribute 和 AttributeType 表中的元数据。

缺点:

非常先进的技术,起初可能难以实施。 它仅适用于少量数据,因为您需要访问许多数据库行来构建单个对象。 您可能希望构建一个小型管理应用程序来维护元数据。 由于需要访问多行来获取单个对象的数据,因此针对这些数据进行报告可能非常困难。

何时使用:

适用于处理少量数据的复杂应用程序,或者数据访问不常见的应用程序,或者您可以将数据预加载到缓存中。

【讨论】:

以上是关于在 MySQL 中实现继承:备选方案和只有代理键的表的主要内容,如果未能解决你的问题,请参考以下文章

一对一关联映射

如何使用 Java Spring 在 MySql 中实现多租户 [关闭]

如何在hibernate中实现继承?

Javascript中实现继承的方式

动态代理

js中实现继承的方法