base 类型和每个具体类型都作为各自的单独表存在。继承表中的FK是PK,与 base 表中的相应记录共享相同的PK值,从而创建了1:0-1关系。这需要一些稍微复杂一些的数据访问逻辑,但这使得在Group Chat上下文中意外检索Private Chat变得更加困难,因为数据需要从正确的表中显式查询。
这通常是最简单的方法,如果你的表在应用程序逻辑中有继承,那么公共属性将在每个表中被复制。这可能导致大量冗余的数据访问逻辑,但是应用程序层中遵循DRY原则的OO继承解决了大多数代码冗余问题。 这个对How can you represent inheritance in a database?的回答从一个更学术和研究的Angular 涵盖了DB继承。 从 * 性能 * 的Angular 来看,如果使用模式明显不同,隔离 * 工作负载 * 会有好处。因此,如果Group Chats具有不同的使用配置文件,则查询的频率或类型明显不同,或者Group Chat中的附加字段将受益于它们自己的索引配置文件。那么拆分表将允许数据库引擎提供更好的索引管理和执行计划优化,因为它可以更准确地捕获表统计信息。 从安全性和相容性的观点来看,单一表格实作(TPH)可以减少资料存取逻辑,因此可以减少程式码的整体攻击面。但是,良好的ORM或程式码产生策略通常可以减轻此空间中可能发生的任何问题。相反地,TPH或简单表格可以让定义数据库或纲要层次安全性原则和限制条件变得更容易。 最终,哪种解决方案最适合您,取决于实现和维护所选应用程序逻辑所需的工作量。 我有时会在同一个数据库中混合使用TPT和TPH,但如果我需要在数据模式中继承,我通常倾向于使用TPT,这篇旧文章解释了我反对TPH的理由:Database Design: Discrimator vs Separate Tables with regard to Constraints。我的一般规则是,如果 type 需要是 * 多态 * 的,要么考虑两种 * type *,要么考虑 type context 在应用程序运行时以某种方式动态更改,则TPT或 * 无继承 * 更易于实现。我使用TPH当类型之间的差异最小并且不期望在应用程序生命周期内合理地偏离太多时,以及当用法和实现将非常相似时,可以使用这种方法。
1条答案
按热度按时间ryevplcw1#
这与一般问题 “是否应将敏感列拆分到新表中” 类似,一般答案是相同的,这在很大程度上取决于数据访问代码和安全框架。
第三种选择呢,为什么不将
Private Chat
建模为组中只有2个成员的Group Chat
?有时候将模型拆分为这些类型是 * 过早的优化 *,特别是在 * 聊天 * 风格的应用程序中。例如,难道 * 私聊 * 不能像 * 群聊 * 一样从图片中获益吗?用户可以为自己的私人群指定一个 * 群名 *,这难道没有什么好处吗?如果只有一种类型的 * 聊天 *,并且由用户决定有多少人可以加入聊天,或者其他人是否可以加入聊天,您会发现应用程序的整个开发和管理要简单得多。
如果你还想探索这两种概念类型,这个答案可能会给予你一些间接的见解:https://stackoverflow.com/a/74398184/1690217,但最终我们需要更多信息来证明选择一种结构而非另一种结构的合理性。性能、安全性和一般数据治理是一些对实施有影响或有警告的考虑因素。
从结构的Angular 来看,您的
Group Chats
和Private Chats
可以都是一个公共Chat
表的实现,从概念上讲,我们可以说这两种形式都从Chat
* 继承 *。在关系数据库中,我们有3种通用的继承模型选项:
*每个层次结构的表(TPH)
使用具有 * 鉴别器列 * 的单个表,该列确定每一行的特定 * 类型 *。然后,在应用程序层或通过视图,您可以查询每种类型和方案所需的特定字段。
*每种类型的表(TPT)
base 类型和每个具体类型都作为各自的单独表存在。继承表中的FK是PK,与 base 表中的相应记录共享相同的PK值,从而创建了1:0-1关系。这需要一些稍微复杂一些的数据访问逻辑,但这使得在
Group Chat
上下文中意外检索Private Chat
变得更加困难,因为数据需要从正确的表中显式查询。简单隔离表(架构中无继承)
这通常是最简单的方法,如果你的表在应用程序逻辑中有继承,那么公共属性将在每个表中被复制。这可能导致大量冗余的数据访问逻辑,但是应用程序层中遵循DRY原则的OO继承解决了大多数代码冗余问题。
这个对How can you represent inheritance in a database?的回答从一个更学术和研究的Angular 涵盖了DB继承。
从 * 性能 * 的Angular 来看,如果使用模式明显不同,隔离 * 工作负载 * 会有好处。因此,如果
Group Chats
具有不同的使用配置文件,则查询的频率或类型明显不同,或者Group Chat
中的附加字段将受益于它们自己的索引配置文件。那么拆分表将允许数据库引擎提供更好的索引管理和执行计划优化,因为它可以更准确地捕获表统计信息。从安全性和相容性的观点来看,单一表格实作(TPH)可以减少资料存取逻辑,因此可以减少程式码的整体攻击面。但是,良好的ORM或程式码产生策略通常可以减轻此空间中可能发生的任何问题。相反地,TPH或简单表格可以让定义数据库或纲要层次安全性原则和限制条件变得更容易。
最终,哪种解决方案最适合您,取决于实现和维护所选应用程序逻辑所需的工作量。
我有时会在同一个数据库中混合使用TPT和TPH,但如果我需要在数据模式中继承,我通常倾向于使用TPT,这篇旧文章解释了我反对TPH的理由:Database Design: Discrimator vs Separate Tables with regard to Constraints。我的一般规则是,如果 type 需要是 * 多态 * 的,要么考虑两种 * type *,要么考虑 type context 在应用程序运行时以某种方式动态更改,则TPT或 * 无继承 * 更易于实现。我使用TPH当类型之间的差异最小并且不期望在应用程序生命周期内合理地偏离太多时,以及当用法和实现将非常相似时,可以使用这种方法。
在 * Chat * 的 上下 文 中 , * * TPT * * 可以 从 * Composition * 的 Angular 工作 。 所有 的 聊天 都 具有 相同 的 基本 功能 和 交互 ,但是
Group Chat
记录 可以 具有 * 扩展 的 * 元 数据 和 行为 。除非 您 设想Private Chat
有 很多 自己 的 特定 实现 , 否则 没有 理由 将Chat
的 基本 概念 扩展 到Private Chat
如果 在 实现 中 没有 差异 , 则 为 " 实现 " 。同样 出于 这个 原因 , 从 数据 库 的 Angular 来看 , 是否 有 必要 区分 * Private * 和 * Group * 聊天 呢 ? 在 这 两 种 情况 下 , 应用 程序 运行 时 都 不 应该 使用 盲目 的
SELECT *
样式 查询 来 访问 数据 , 它 应该 请求 给定 上下文 所 需 的 特定 字段 , 无论 您 是否 在 表 中 使用 了 * Field * ,、 或 表 的 * 名称 * 来 区分 不同 的 概念 不如 能够 证明 这些 概念 的 存在 或 这些 概念 之间 的 差异 重要 。