首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >MySQL -我应该在每个子表上使用多列主键吗?

MySQL -我应该在每个子表上使用多列主键吗?
EN

Stack Overflow用户
提问于 2011-09-08 20:46:39
回答 3查看 1.1K关注 0票数 0

设置:

当我在stackexchange上找到这篇伟大的文章时,我正试图理解标识关系和非标识关系之间的区别。What's the difference between identifying and non-identifying relationships?

在读了几句评论后,我想起了另一个关于我所遇到的问题的问题。

问题:

我应该在每个子表上使用多列主键吗?这样做的优缺点是什么?

为了更好地说明我的问题,我创建了下面的一个例子。我还包括了引起我提出这个问题的意见。

示例:

在我的情况下,我知道building_id,我需要得到bed.data

#1 -我当前的DB结构:

代码语言:javascript
复制
TABLE { FIELDS }
-----------------------------------------------------------------------
building { id, data } 
floor { id, building_id, data }
room {id, floor_id, data }
bed {id, room_id, data }

这种类型的表结构需要我使用几个联接来获取我需要的数据。没什么大不了的,但我经常遇到这种情况,所以有点痛苦。

#2 -我对Bill建议的DB结构的解释(见下面的文章注释):

代码语言:javascript
复制
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的单列伪键定义其主键,该id自动生成它的值。Rails等应用程序框架已经将其推广为默认设置。他们将自然键和多列键视为与使用“遗留”数据库时所需的约定不同的键。许多其他框架也遵循了这一思路。-比尔·卡温( Bill Karwin ),3月10日23:06

似乎“正确地”构建标识关系会导致巨大的主键。楼有地板有房间有床。床的PK为(bed_id,floor_id,room_id,building_id)。奇怪的是,我从来没有在实践中见过这个,也没有听说过它是一种做任何事情的方法。这是PK中的大量冗余数据。-3月10日23:34

@霍博达夫:我见过更大的多列主键。但我接受你的观点。请考虑多列主键传递更多信息;您可以在不进行任何连接的情况下查询特定建筑物中所有床位的床表。-比尔·卡温(BillKarwinMar11 '10 ) 1:00

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-08 20:52:59

这些数据是标准化的。

代码语言:javascript
复制
TABLE { FIELDS }
-----------------------------------------------------------------------
building { id, data } 
floor { id, building_id, data }
room {id, floor_id, data }
bed {id, room_id, data }

这张桌子不错(好主意)

代码语言:javascript
复制
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 }

在第一个(好的)表中,

  1. 没有不必要的重复数据。在第一个表中插入
  2. 要快得多。
  3. --第一个表将更容易地放入内存中,从而加快查询速度。
  4. InnoDB是在考虑模型A的情况下进行优化的,而不是使用B模型进行优化的。
  5. (坏的)表有重复的数据,如果不同步,则会造成混乱。DB A很难脱离同步,因为数据只列出一次。
  6. ,如果我想把A型和B型的data从大楼、楼层、房间和床上合并起来,你在这里怎么节省时间?select
  7. InnoDB将索引数据存储在它自己的文件中,如果您只为索引,则表本身将不会被访问。那么你为什么要复制索引呢?无论如何,MySQL都不需要读取主表。
  8. InnoDB将PK 存储在每个次要索引中,使用一个复合的和长的PK,您正在减慢使用索引和平衡文件大小的每一个选择;无论如何,都不会得到任何好处。
  9. 你有严重的速度问题吗?如果不是,您是否正在对表进行反错操作?
  10. 甚至都不考虑使用受这些问题影响较小的MyISAM,它不是针对多连接数据库进行优化的,也不支持引用完整性或事务,而且使用复合键对此floor_id的匹配很差--您只能使用键的最右边的部分,也就是说,除了使用id+building_id+floor_id之外,不能在表bed中使用floor_id,这意味着您可能必须使用比模型A中需要的更多的密钥空间,或者您需要添加一个额外的索引(这将拖曳PK的完整副本)。

In

我看到了绝对零的好处和许多缺点,在模式B,永远不要使用它!

票数 3
EN

Stack Overflow用户

发布于 2011-09-09 00:29:02

我认为你的第二名不太可能是比尔·卡温的意思。通常,"id“意味着自动数字序列。我觉得他更有可能是这么说的。组成主键的列在星号之间。

代码语言:javascript
复制
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 }

不过,我不知道你还有什么“床”专栏。双胞胎,满的,王后,国王?这可能是有道理的。如果是这样,那么这张桌子

代码语言:javascript
复制
bed      { *building_id, floor_num, room_num, bed_num*, bed_size }

远非“非正常化”。事实上,它是在5NF中。

如果您测试这两个模式的性能,您可能会发现这个模式在大多数情况下都围绕您的#1运行。在我运行的一批查询中,速度大约快了30倍。

票数 3
EN

Stack Overflow用户

发布于 2011-09-08 21:05:49

第一个表结构是规范化的,经典结构。但不幸的是,这个并不适用于大型项目。因为如果您的表构建包含许多数据行,例如百万行,取决于您使用的城市或国家,您的联接将非常缓慢。因此,在实际项目中,使用非规范化表,其中包含所有聚合信息。您可以直接使用这些表,也可以使用像sphinx这样的独立服务器来搜索数据。关于三个字段的主键,我认为在这个例子中,这个是多余的。因为

如果您使用

  1. ,则此键将添加到此表中的所有辅助键中。如果您使用接口来管理床,则使用一个字段id处理特定行比使用三个字段更方便。如果要保证行的唯一性,则可以在这3个字段上使用唯一的键。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7354271

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档