我正在为MySQL
实体在电子商务上下文中的Customer
(通过Prisma数据模型)模式进行研究。随着领域的数量激增(包括参与度跟踪),我在这里有两种可能的设计:
type Customer {
email: String! @unique
name: String
birthDate: DateTime
addresses: [Address!]!
...
productsVisited: [Product!]!
productsShared: [Product!]!
productsSearched: [Product!]!
...
}
应该将应该一起传达信息的字段雕刻到自己的表中,并通过一对一关系将其与上一个表连接起来:
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!]!
}
问题:
这里思考设计的正确方法是什么?目前,我受ER图和直觉的驱动。通过使表变薄可以节省或失去执行力或灵活性方面的优势吗?列数?
在第二种方法中,查询是否需要为表联接做额外的工作?
摘要问题:
在架构或性能标准不断发展的情况下,一种方法是否绝对优于另一种方法?或者,这只是这里的味道吗?
答案 0 :(得分:2)
这两种方法肯定都可以使用,并且确实在某种程度上取决于您的个人喜好以及处理数据时要使用的API。
使用您概述的第二种方法,Prisma实际上将为CustomerProfile
,ProductEngagement
和所有其他类型创建表(作为一般规则,Prisma将数据类型中的所有类型定义映射到它们的自己的表)。因此,正如@ rick-james指出的那样,在检索数据时,JOIN
中可能需要执行一些开销。
这里思考设计的正确方法是什么?我目前受到ER图的驱动。
这通常是一种有效的方法,因为Prisma数据模型最终会映射到数据库。从这种意义上讲,最好以ER图的形式来考虑它。
还请注意,Prisma很快将支持嵌入式类型,该类型允许在Prisma数据模型中定义一个类型,该类型不具有自己的表,而是将数据存储在内部的JSON列中非嵌入式类型的表。将Prisma与MongoDB一起使用时,当前已经支持此功能,但尚未与SQL一起使用。您可以在this feature request中了解有关此主题的更多信息。
答案 1 :(得分:1)
在RDBMS中,几乎没有任何充分的理由将表以1:1关系拆分为两个表。将它们JOIN
一起SELECT
放在一起当然是可能的,但是会增加一些开销,代码复杂性,并且对性能造成轻微的影响。
话虽这么说,但我很少(遇到)这种“垂直分区”是有益的情况。
JOIN
,并且通常可以避免潜在的“笨重”性能。ALTER TABLE
命令的成本很高(认为是停机时间),以至于您迫切希望找到避免这种情况的方法...这样一个单独的表很快,简单等。(但是,当然需要JOIN
带来的不便等。)NULLs
填充这些列(要做的事情)。但是将它们拆分后,您在另一个表中根本就没有一行。然后,您使用LEFT JOIN
,从而凭空重建NULLs
。