【问题标题】:Why have a 1:1 Relationship - Database Design?为什么要建立 1:1 关系 - 数据库设计?
【发布时间】:2016-09-23 21:05:30
【问题描述】:

我正在查看现有的数据库架构,但我对以下示例中的 1:1 关系有点困惑:

Event
-----
id  int (PK)
Title varchar
Description varchar
OrganizerId int (FK)


EventSchedule
------------
id int (Pk)
EventId int (FK)
Start datetime
End   datetime
RepeatRule varchar (ical format for repeating events)  

Venue
-----
id int (PK)
EventId (FK)
Name  varchar
Address1 varchar
Address2 varchar
City varchar
Region varchar
Postcode varchar
latitude float
longitude float

活动只在一个地点举行,因此活动和场地之间存在 1:1 的关系。 同样,Event 与 EventSchedule 具有 1:1 的关系 - ical repeat 规则捕获重复事件。

这样分隔表格是否有任何理由或实例?如下有一个表会有什么问题:

Event
-----
id int (PK)
Title varchar
Description varchar
OrganizerId int (FK)
Start datetime
End   datetime
RepeatRule varchar (ical format for repeating events) 
Venue  varchar
Address1 varchar
Address2 varchar
City varchar
Region varchar
Postcode varchar
latitude float
longitude float 

对于每种设计的优缺点,我们将在上述上下文中特别赞赏一些建议,以使架构足够灵活,以供将来考虑世界场景,即 1:1 到 1:N 等。

【问题讨论】:

  • 提议的模式似乎更灵活,可以接受大多数类型的事件,而你的模式似乎高度专业化(我发现场地不太可能只使用一次,并且发生的事件超过一次对我来说似乎并不罕见)。因此,答案通常是正确的答案可能完全取决于您的用例......
  • 正如 fvu 所提到的,作为场地不太可能只使用一次。它也是分离所有实体类型的最佳实践(第 3 范式)。有了适当的规范化数据库,未来的开发和灵活性会容易得多。此外,您将能够在报告数据时消除复杂的查询。如果您的活动可以在不同的地点多次发生,我会尽可能创建 3 张桌子。 EventType(活动信息,如描述、名称等)、Events(场地与 EventType 之间的关系、日期、具体活动详情等)和场地。
  • @fvu Venue 表包括 FK EventId,它是 1:1 的关系。一个事件不能在多个位置发生 - 如果是,那么它将被归类为不同的事件并为该事件创建一个新记录。如果在同一地点发生了另一个事件,则会将具有相同地址详细信息的新记录插入到地点表中。那么如何使用同一个场地呢?同样,如果一个事件发生不止一次,详细信息将包含在 ical 重复规则中,即无需在 EventSchedule 表中为同一事件创建一行。
  • @ozzii 我忽略了 Venue 以这种方式与 Event 相关联的事实,这确实很奇怪。我宁愿在 Event 中使用 VenueId。 Wrt Eventschedule,例如,如果一个事件重复了 4 次但开始时间不同怎么办?无论如何,原来的结构似乎有严重的问题。
  • @fvu 为什么要在 Event 中使用 VenueId?组织者填写表格以创建活动,其中包括提供地点/地址详细信息。根据您的提议,如果不同的组织者在他们的活动中使用相同的场地记录,如果其中一个组织者决定更新场地/地址详细信息会发生什么。它将使用该 VenueId 级联到所有其他事件 - 这会很糟糕。

标签: database-design relationship database-schema one-to-one


【解决方案1】:

分开的一个原因是避免在场地和日程表中使用空值,如果它们在设置事件记录时未知。

分开的另一个原因是你现在有一对一的关系,但是当你没有一对一的关系时,有人可能正在计划未来。我当然见过这些类型的事情,其中​​事件发生在多个地点并且有多个时间表。

由于场地可能会被重复用于不同的活动,我会设计一个场地表和一个 EventVenue 表以避免重复所有地址和 GPS 数据。

分离的另一个原因可能与数据的使用方式有关。如果您并不总是需要所有查询中的所有信息,有时将它们分散到其他表中是有意义的。

分离的另一个原因是,许多人更喜欢根据逻辑上的组合进行建模。

分离的另一个原因与不太宽的表有关,往往查询速度更快(特别是如果您不需要总是查询其他信息),有时所有字段加在一起会形成一个更宽的表大于 SQL Server 记录的有效行大小。如果满足每个字段的最大大小,这将导致您无法将这些记录添加到该表中,即使 SQL Server 允许您创建它。

【讨论】:

  • 用例是组织者在创建活动时需要提供场地和地址。我承认可以为不同的活动重新使用场地,但由于不同的组织者正在创建活动,相同的场地 ID/记录不能用于其他组织者创建的活动。否则,每当组织者决定编辑活动并更改场地详细信息时,更改将级联到使用相同场地 ID 的所有其他活动,这不是预期的功能。请注意,场地/地址是由组织者手动创建的。这不是查找表。
  • 您能否为您对日期开始停止的建议提供一个架构,以便过去的事件将保留旧版本的地址,而新的将使用当前地址
  • 请注意,场地/地址/gps 是使用谷歌地址查找完成的。将它们存储在场地表中以避免重复所有地址/gps 数据不会满足任何功能性业务需求,因为它不太可能用作查找表,因为它仅包含先前创建的事件的地址。将其与 google 地址搜索一起作为查找表连接起来毫无用处。我认为您只是从数据库的角度而不是实际的现实世界功能应用程序来看待这个问题。
【解决方案2】:

在 1:1 关系中拥有两个表的一个原因是该关系是否是可选的。例如,如果一个事件可以存在而没有事件时间表。最好将其描述为一对零或一。在这种情况下,一个简单的连接可以消除计划外的事件。这比与 NULLS 搏斗要容易得多。

在这种情况下,性能方面的考虑是次要的,并且可以采用任何一种方式,具体取决于您使用数据的方式。

【讨论】:

    【解决方案3】:

    我能想到的两个原因,对表进行规范化是这样的:

    1. 您有一些在 EventSchedule/Venue 上运行的 ORM,但您很少对事件名称感兴趣,例如
    2. 这样迁移速度更快。假设您有 1M 行,并且需要从建议的解决方案向您的事件表添加另一行。您的迁移会将表锁定很长时间。迁移行数较少的表会更快。

    【讨论】:

    • 如果我正在使用 entityframework 并且有一个表单来创建/编辑一个事件(该表单将显示所有 3 个表中的字段)我将不得不更新 3 个表,从而增加复杂程度而没有任何真正的价值。如果我正在查询按位置和日期搜索事件,我必须添加额外的连接,再次没有任何真正的好处?您提到了迁移和性能,但没有考虑到所有 3 个表都将具有相同的行数 - 它的 1:1 关系。如果我在事件表中添加一行,则业务规则规定其他两个表中需要有相应的行。
    【解决方案4】:

    还有另一个原因:在微服务架构中,您可能有多个服务,每个服务负责不同的活动,例如事件和时间表。

    如果每个人都有自己的表,它们会更好地隔离,并在服务之间使用消息传递来传递所需的数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-01
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 2011-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多