Mysql 数据库需不需要主键 Id?

2020-03-19 10:20:04 +08:00
 wangbenjun5

最近接触了一个项目,里面的数据库设计让我“大开眼界”,很多表没有主键 id,取而代之的是复合主键,也就是几个字段同时作为主键,比如说: A 表:

name
age
addr

主键是 name+age

B 表:

name
age
money
something
xxx

主键也是 name+age

实际上 B 表是 A 表的附属表,也就说是补充 A 表的内容,或者是关联到其它表

恕我愚昧,不知道这种设计有什么好处,我觉得用 id 当主键更简介方便,便于修改数据,比如上面的例子有时候还有修改 age 的需求,这时候就非常麻烦了,难道这是反范式化设计,故意做的数据冗余,我不敢苟同,咱也不敢问,咱也不敢说。

各位大佬,求打醒!!!

13593 次点击
所在节点    MySQL
99 条回复
CEBBCAT
2020-03-19 19:15:47 +08:00
这个帖子发得很一般,一来是举的例子时候被发现是不恰当的例子,二来是这帖子根本不是在探讨,只是在吐槽
cabing
2020-03-19 19:47:35 +08:00
这种写法很棒 :)
cabing
2020-03-19 19:49:08 +08:00
补充下,真是需要脑洞的啊。
tairan2006
2020-03-19 21:14:12 +08:00
肯定是用自增啊。。楼主说的这个更适合用复合唯一索引。
reeco
2020-03-19 21:57:29 +08:00
曾经我有一张单表撑了 1 亿多的数据,大量重复的数据在里面,要筛选出来删除。啥索引都不好使了,只能通过自增 id 遍历,加载一部分到内存里慢慢筛选,慢慢删除。那一刻我真的感谢当时用了 id 自增这玩意
whywhywhy
2020-03-19 22:17:48 +08:00
我之前用过一个小 erp,没有主键,我的 sql 编辑器为了防止出错,在更新内容的时候采用 where 所有字段,然后还 top 1,感觉太不可思议了
wangchonglie
2020-03-19 22:30:12 +08:00
@wmhx #70 选取主键的一个基本原则是:不使用任何业务相关的字段作为主键。因为主键是用来唯一定位记录的,修改了主键,会造成一系列的影响。因此,身份证号、手机号、邮箱地址这些看上去可以唯一的字段,均不可用作主键。
Aresxue
2020-03-19 23:31:02 +08:00
elasticsearch 就是这么做的。。。主键的作用是作为数据库组织数据用的,以 mysql 为例默认的 innodb 使用聚簇索引, 决定了数据的位置, 辅助索引也都会带上主键信息, 所以选择随着时间递增且占用空间较小的主键比较符合时间局部性原理,能够充分利用磁盘预读
eggache0914
2020-03-20 01:23:53 +08:00
这同名咋办?。。。。
learningman
2020-03-20 01:28:29 +08:00
@fx 选修过数据库设计就不会干这种事。。。
xingheng
2020-03-20 02:41:18 +08:00
头一次见识这样的“附属表”设计,真是“涨姿势”了
bzj
2020-03-20 06:45:44 +08:00
有些表是可以不用主键的,楼主学一下 EAV 模型
bzj
2020-03-20 06:46:16 +08:00
@bzj 漏了 2 个字 不用 id 作为主键
luzihang
2020-03-20 06:47:25 +08:00
K 线数据,可以用复合,股票代码➕时间
justin2018
2020-03-20 09:59:41 +08:00
阿里新零售数据库设计与实战
非推广
nesuk
2020-03-20 10:02:05 +08:00
必须要自增主键,没有商量的余地,也没有必要在这方面耗费精力。
MonoLogueChi
2020-03-20 13:06:58 +08:00
MySQL 墙裂推荐使用自增主键,非自增主键效率会差很多,没有主键更差,其他数据库的话,有的可能对非自增主键支持好一点,效率上不会比自增主键差太多
realpg
2020-03-20 20:08:11 +08:00
按需而论。
并不是所有的项目都需要自增 ID 或者 UUID 主键。

对于简单项目的部分场景,直接用复合主键同时约束组合唯一性,大数据量节省资源也正常。
passerbytiny
2020-10-16 17:50:24 +08:00
最近在设计事件存储,看了 mysql 索引的数据结构,搜索时把这贴给搜出来了,然后需要纠正一些自己之前回复的错误。

InnoDB 引擎中,插入数据时,顺序(不一定要自增)主键确实比离散主键好。因为:1,InnoDB 引擎的表的背后存储就是聚集索引,通常是一个以主键值为 key 的 B +树,主键索引结构直接影响表数据的文件结构; 2,虽然插入总会导致 B +树分裂,但顺序插入时只在一侧分裂,而离散插入时随机分裂; 3,若 B +树只在一侧分裂则它的终端节点是有序增加的,进而可以与磁盘上连续的磁盘分页对应起来,从而可以连续写入磁盘,否则就只能随机写入磁盘(会增加 IO 时间,制造磁盘碎片)。

但是我仍然推荐用 UUID 而不是自增作为主键。因为:1,自增主键不具备业务性; 2,虽然通过层超模型+ Hibernate 可以实现自增代理主键加业务自然主键的双主键模式来完美解决,但是这样实现的门槛不低; 3,非大量数据时,离散主键并没有损失多少性能,而到讨论性能的时候往往也要分布式了,那时候也用不了自增主键,要用雪花主键。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/654133

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX