关系数据库模式设计——如何根据实体的字段集对一对一映射进行建模
Relational DB schema design - How to model 1-to-1 mapping right from an entity's set of fields
我正在为电子商务环境中的 Customer
实体开发 MySQL
(通过 Prisma 数据模型)架构。随着字段数量的激增(包括参与度跟踪),我在这里有两种可能的设计:
type Customer {
email: String! @unique
name: String
birthDate: DateTime
addresses: [Address!]!
...
productsVisited: [Product!]!
productsShared: [Product!]!
productsSearched: [Product!]!
...
}
那个,或者应该一起传递信息的字段应该分割成它们自己的table,并通过一对一的关系连接到前一个:
type Customer {
profile: CustomerProfile! @relation(name: "CustomerProfile", onDelete: CASCADE)
addresses: [Address!]!
...
productEngagements: ProductEngagement! @relation(name: "CustomerProductEngagements", onDelete: CASCADE)
...
}
type CustomerProfile {
customer: Customer! @relation(name: "CustomerProfile", onDelete: SET_NULL)
email: String! @unique
name: String
birthDate: DateTime
}
type ProductEngagement {
customer: Customer! @relation(name: "CustomerProductEngagements", onDelete: SET_NULL)
productsVisited: [Product!]!
productsShared: [Product!]!
productsSearched: [Product!]!
}
问题:
What is the right way of thinking design here? I am currently driven by my ER diagrams, and intuition. Do I get or lose any execution or flexibility advantage with making a table thin w.r.t. number of columns?
In the second method, do queries have to do extra work for table joins?
抽象问题:
Is a method definitely better than the other, given evolving schema, or performance criteria? Or, is this just a matter of taste here?
在 RDBMS 中,很少有充分的理由将 table 拆分为 1:1 关系中的两个 table。 JOIN
它们在 SELECT
中重新组合在一起当然是可能的,但会增加一些开销、代码复杂性,并且对性能有轻微影响。
也就是说,我(很少)遇到这样的 "vertical partitioning" 是有益的情况。
- 一个 table 中有 "too many" 列,拆分避免达到某些数据库限制...(这种情况可能由其他解决方案更好地处理。)
- 有些列既笨重又很少使用...通过将它们移动到单独的 table,通常可以避免
JOIN
,并且 [=34= 的潜在性能下降] 通常会被避免。
- 您需要向巨大的 table 添加一些列,但是
ALTER TABLE
命令的成本如此之高(思考,停机时间),您迫切希望找到一种方法来避免它...这样一个单独的 table 是快速、简单等(但是,当然,需要 JOIN
带来的不便等)
- 您有一组很少出现在 table 中的列...在拆分它们之前,您打算用
NULLs
填充这些列(有效的做法)。但是将它们分开后,您根本就没有其他 table 中的一行。然后你使用一个LEFT JOIN
,从而凭空重建NULLs
。
这两种方法肯定都行得通,这确实在某种程度上取决于您的个人喜好以及您在处理数据时希望拥有的API。
使用您概述的第二种方法,Prisma 确实会为 CustomerProfile
、ProductEngagement
和所有其他类型创建 tables(作为一般规则,Prisma 映射所有类型定义从你的数据模型到他们自己的 tables)。因此,正如@rick-james 指出的那样,检索数据时需要执行的 JOIN
中可能存在开销。
What is the right way of thinking design here? I am currently driven by my ER diagrams.
这通常是一种有效的方法,因为 Prisma 数据模型最终映射到数据库。从这个意义上说,用ER图来思考应该没问题。
另请注意,Prisma 将很快支持 嵌入式类型 ,这允许在 Prisma 数据模型中定义一个类型,该类型没有自己的 table 但数据所在的位置而是存储在非嵌入类型的 table 内的 JSON 列中。目前,在 MongoDB 中使用 Prisma 时已经支持此功能,但在 SQL 中尚不支持。您可以在 this feature request.
中了解有关此主题的更多信息
我正在为电子商务环境中的 Customer
实体开发 MySQL
(通过 Prisma 数据模型)架构。随着字段数量的激增(包括参与度跟踪),我在这里有两种可能的设计:
type Customer {
email: String! @unique
name: String
birthDate: DateTime
addresses: [Address!]!
...
productsVisited: [Product!]!
productsShared: [Product!]!
productsSearched: [Product!]!
...
}
那个,或者应该一起传递信息的字段应该分割成它们自己的table,并通过一对一的关系连接到前一个:
type Customer {
profile: CustomerProfile! @relation(name: "CustomerProfile", onDelete: CASCADE)
addresses: [Address!]!
...
productEngagements: ProductEngagement! @relation(name: "CustomerProductEngagements", onDelete: CASCADE)
...
}
type CustomerProfile {
customer: Customer! @relation(name: "CustomerProfile", onDelete: SET_NULL)
email: String! @unique
name: String
birthDate: DateTime
}
type ProductEngagement {
customer: Customer! @relation(name: "CustomerProductEngagements", onDelete: SET_NULL)
productsVisited: [Product!]!
productsShared: [Product!]!
productsSearched: [Product!]!
}
问题:
What is the right way of thinking design here? I am currently driven by my ER diagrams, and intuition. Do I get or lose any execution or flexibility advantage with making a table thin w.r.t. number of columns?
In the second method, do queries have to do extra work for table joins?
抽象问题:
Is a method definitely better than the other, given evolving schema, or performance criteria? Or, is this just a matter of taste here?
在 RDBMS 中,很少有充分的理由将 table 拆分为 1:1 关系中的两个 table。 JOIN
它们在 SELECT
中重新组合在一起当然是可能的,但会增加一些开销、代码复杂性,并且对性能有轻微影响。
也就是说,我(很少)遇到这样的 "vertical partitioning" 是有益的情况。
- 一个 table 中有 "too many" 列,拆分避免达到某些数据库限制...(这种情况可能由其他解决方案更好地处理。)
- 有些列既笨重又很少使用...通过将它们移动到单独的 table,通常可以避免
JOIN
,并且 [=34= 的潜在性能下降] 通常会被避免。 - 您需要向巨大的 table 添加一些列,但是
ALTER TABLE
命令的成本如此之高(思考,停机时间),您迫切希望找到一种方法来避免它...这样一个单独的 table 是快速、简单等(但是,当然,需要JOIN
带来的不便等) - 您有一组很少出现在 table 中的列...在拆分它们之前,您打算用
NULLs
填充这些列(有效的做法)。但是将它们分开后,您根本就没有其他 table 中的一行。然后你使用一个LEFT JOIN
,从而凭空重建NULLs
。
这两种方法肯定都行得通,这确实在某种程度上取决于您的个人喜好以及您在处理数据时希望拥有的API。
使用您概述的第二种方法,Prisma 确实会为 CustomerProfile
、ProductEngagement
和所有其他类型创建 tables(作为一般规则,Prisma 映射所有类型定义从你的数据模型到他们自己的 tables)。因此,正如@rick-james 指出的那样,检索数据时需要执行的 JOIN
中可能存在开销。
What is the right way of thinking design here? I am currently driven by my ER diagrams.
这通常是一种有效的方法,因为 Prisma 数据模型最终映射到数据库。从这个意义上说,用ER图来思考应该没问题。
另请注意,Prisma 将很快支持 嵌入式类型 ,这允许在 Prisma 数据模型中定义一个类型,该类型没有自己的 table 但数据所在的位置而是存储在非嵌入类型的 table 内的 JSON 列中。目前,在 MongoDB 中使用 Prisma 时已经支持此功能,但在 SQL 中尚不支持。您可以在 this feature request.
中了解有关此主题的更多信息