数据库设计,减少连接
Database design, reducing join
这是门票在线商店的数据库(例如 Airbnb 体验)
对于产品(工单),
有可用的天数(和时间)
在有空的那一天,
- 可以有多个选项(例如 beginner-class, advanced-class)
- 有可售数量(多选共享)
一种表示方式是
Product
name
Variant (Option)
product
TimeSlot
product
date
time
quantity
TimeslotVariant
variant
timeslot
另一种方法如下。
我看到两个主要区别,
一阶差
- 上图:您需要加入
TimeSlot
才能找到特定日期的变体。
- 以下:可以直接查询
TimeVariant
二差
- 以上:
[{date, time, [variant1, variant2], quantity}]
(我认为客户端应用程序更喜欢这个)
- 以下:
[{date, time, variant1}, {date, time, variant2}]
+ [{date, time, quantity}]
Product
name
Variant (Option)
product
TimeSlot
product
date
time
quantity
TimeVariant
variant
date
time
我认为第一个选项更直观 (?) 但我也认为有时维护额外的连接会很痛苦
我应该问自己哪些问题(标准)以在两者之间做出决定?
恕我直言,连接数可能不是您在设计关系数据库时需要问自己的最重要的问题。
最重要的问题是如何确保保护数据完整性。
数据完整性最好与您提供的第一个选项保持一致,因此这是您应该选择的选项。
如果连接是困扰您的问题,您可以随时使用视图 "flatten" 数据。
但为什么第一个选项更好?
因为 TimeSlot
table 的主键(或者至少是自然键)必须由 product
、date
和 time
组成 - 而第二个TimeVariant
table 选项没有考虑产品。
您也可以将 product
添加到 table 中,一些 DBA 会建议将其作为最佳选择(那些反对使用代理键的 DBA)- 但是就个人而言,尽管我自己不是 DBA,但我认为代理键有它的优势,其中之一正是你在这里所拥有的——你可以使用一个列而不是三个列来连接两个 tables -这让你的生活更轻松(并且通过强制执行 table 的自然键的唯一性,代理键没有完整性问题)。
首先您应该考虑是否要减少加入开销?如果是,那么您可以使用存储在视图中的展平数据。
第一个案例
在 TimeslotVariant 中,您添加了 variant 和 timeslot,仅通过查询TimeslotVariant table 你会得到你想要的数据。在这种情况下,您的数据完整性没问题。
第二个案例
如果您将产品密钥添加到您的 TimeslotVariant,那么仅显示产品列表将达到目的,但时间和日期也会重新输入。
我的建议是保留第一种情况并将展平数据存储在视图中。
这是门票在线商店的数据库(例如 Airbnb 体验)
对于产品(工单),
有可用的天数(和时间)
在有空的那一天,
- 可以有多个选项(例如 beginner-class, advanced-class)
- 有可售数量(多选共享)
一种表示方式是
Product
name
Variant (Option)
product
TimeSlot
product
date
time
quantity
TimeslotVariant
variant
timeslot
另一种方法如下。
我看到两个主要区别,
一阶差
- 上图:您需要加入
TimeSlot
才能找到特定日期的变体。 - 以下:可以直接查询
TimeVariant
- 上图:您需要加入
二差
- 以上:
[{date, time, [variant1, variant2], quantity}]
(我认为客户端应用程序更喜欢这个) - 以下:
[{date, time, variant1}, {date, time, variant2}]
+[{date, time, quantity}]
- 以上:
Product
name
Variant (Option)
product
TimeSlot
product
date
time
quantity
TimeVariant
variant
date
time
我认为第一个选项更直观 (?) 但我也认为有时维护额外的连接会很痛苦
我应该问自己哪些问题(标准)以在两者之间做出决定?
恕我直言,连接数可能不是您在设计关系数据库时需要问自己的最重要的问题。
最重要的问题是如何确保保护数据完整性。 数据完整性最好与您提供的第一个选项保持一致,因此这是您应该选择的选项。
如果连接是困扰您的问题,您可以随时使用视图 "flatten" 数据。
但为什么第一个选项更好?
因为 TimeSlot
table 的主键(或者至少是自然键)必须由 product
、date
和 time
组成 - 而第二个TimeVariant
table 选项没有考虑产品。
您也可以将 product
添加到 table 中,一些 DBA 会建议将其作为最佳选择(那些反对使用代理键的 DBA)- 但是就个人而言,尽管我自己不是 DBA,但我认为代理键有它的优势,其中之一正是你在这里所拥有的——你可以使用一个列而不是三个列来连接两个 tables -这让你的生活更轻松(并且通过强制执行 table 的自然键的唯一性,代理键没有完整性问题)。
首先您应该考虑是否要减少加入开销?如果是,那么您可以使用存储在视图中的展平数据。
第一个案例
在 TimeslotVariant 中,您添加了 variant 和 timeslot,仅通过查询TimeslotVariant table 你会得到你想要的数据。在这种情况下,您的数据完整性没问题。
第二个案例
如果您将产品密钥添加到您的 TimeslotVariant,那么仅显示产品列表将达到目的,但时间和日期也会重新输入。
我的建议是保留第一种情况并将展平数据存储在视图中。