当我在stackexchange上发现这篇精彩的文章时,我试图理解识别和非识别关系之间的区别。 What's the difference between identifying and non-identifying relationships?
在阅读了一些评论之后,我又想到了一个问题,我想到了一个问题。
我应该在每个子表上使用多列主键吗?这样做有哪些优点/缺点?
为了更好地说明我的问题,我在下面创建了一个示例。我还提到了让我提出这个问题的评论。
在我的情况下,我知道building_id
,我需要bed.data
。
#1 - 我目前的数据库结构:
TABLE { FIELDS }
-----------------------------------------------------------------------
building { id, data }
floor { id, building_id, data }
room {id, floor_id, data }
bed {id, room_id, data }
这种类型的表结构需要我使用一些连接来获取我需要的数据。我遇到了很多这样的情况,但并不是什么大不了的事情。
#2 - 我对Bill Karwin建议的数据库结构的解释(参见下面的文章评论):
TABLE { FIELDS }
-----------------------------------------------------------------------
building { id, data }
floor { id, building_id, data }
room {id, building_id, floor_id, data }
bed {id, building_id, floor_id, room_id, data }
这种表结构似乎在我的情况下消除了连接的需要。那么这个表结构的缺点是什么?我真的很喜欢不做这么多连接声明的想法。
What's the difference between identifying and non-identifying relationships?
@hobodave:这是“约定优于配置”参数。有些思想认为,每个表都应该为一个名为id的单列伪代码定义其主键,以自动生成其值。像Rails这样的应用程序框架已将其推广为默认值。它们将自然键和多列键视为与使用“遗留”数据库时所需的约定不同。许多其他框架都遵循这一主导。 - Bill Karwin 2010年3月10日23:06
似乎“正确”构建识别关系会导致令人讨厌的巨大主键。例如大楼有地板有房间有床。床的PK将是(bed_id,floor_id,room_id,building_id)。看起来很奇怪,我从未在实践中看到这一点,也没有听说它是一种做任何事情的方式。这是PK中的大量冗余数据。 - hobodave 2010年3月10日23:34
@hobodave:我见过更多的多列主键。但我明白你的观点。考虑多列主键传达更多信息;您可以查询床位,了解特定建筑物中的所有床位,而无需进行任何连接。 - Bill Karwin 2010年3月11日凌晨1点
答案 0 :(得分:3)
此数据已标准化
TABLE { FIELDS }
-----------------------------------------------------------------------
building { id, data }
floor { id, building_id, data }
room {id, floor_id, data }
bed {id, room_id, data }
这张表不是(坏主意)
TABLE { FIELDS }
-----------------------------------------------------------------------
building { id, data }
floor { id, building_id, data }
room {id, building_id, floor_id, data }
bed {id, building_id, floor_id, room_id, data }
select
仅索引,表格本身将从不访问。那你为什么要复制索引呢?无论如何,MySQL永远不需要读取主表。 floor_id
之外,您无法在表bed
中使用id+building_id+floor_id
,这意味着您可能必须使用比模型A中所需更多的键空间。或者你需要添加一个额外的索引(它将拖动PK的完整副本)。 简而言之
我在模型B中看到绝对零利益和许多缺点,从不使用它!
答案 1 :(得分:3)
我认为你的#2不太可能是Bill Karwin的意思。通常,“id”表示自动数字序列。我认为他更有可能在这些方面表达意义。构成主键的列位于星号之间。
TABLE { COLUMNS }
-----------------------------------------------------------------------
building { *building_id*, other columns }
floor { *building_id, floor_num*, other columns }
room { *building_id, floor_num, room_num*, other columns }
bed { *building_id, floor_num, room_num, bed_num* (?), other columns }
我不确定你可能会为“床”提供哪些其他专栏。双床房,全套房,大床房,特大床房这可能有意义。如果是这样的话,那么这个表
bed { *building_id, floor_num, room_num, bed_num*, bed_size }
远非“非规范化”。事实上,它在5NF。
如果你测试这两个模式的性能,你可能会发现这个模式在大多数情况下绕着#1运行。在我运行的一批查询中,它的速度提高了大约30倍。
答案 2 :(得分:0)
第一个表格结构是规范化的,经典的结构。但不幸的是,这个不适用于大项目。因为如果您的表构建包含许多数据行,例如百万取决于您使用加入的城市或国家/地区将非常缓慢。 因此在实际项目中使用包含所有聚合信息的非规范化表。您可以直接使用此类表,也可以使用sphinx等独立服务器来搜索数据。关于三个领域的主键,我认为在这种情况下,这个是多余的。因为