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 的需求,这时候就非常麻烦了,难道这是反范式化设计,故意做的数据冗余,我不敢苟同,咱也不敢问,咱也不敢说。

各位大佬,求打醒!!!

13516 次点击
所在节点    MySQL
99 条回复
opengps
2020-03-19 11:15:57 +08:00
可以不用主键。
但是不用主键的时候,聚集索引列的设置一定要合理。

另外会引发某些其他问题:例如 EF 对无主键表不能自动代码生成

看我的使用案例(虽然是 SQL server ): https://www.opengps.cn/Blog/View.aspx?id=284&from=v2ex
rockyou12
2020-03-19 11:19:20 +08:00
复合主键其实设计上,在很多业务中是最优解( lz 这个当然不合适)。但确实容易出性能问题,我觉得和 mysql 本身不优化性能过烂也不无关系……
aliasliyu4
2020-03-19 11:21:13 +08:00
开心就好
aliasliyu4
2020-03-19 11:21:56 +08:00
可以试试不要 痛过才知道香
optional
2020-03-19 11:24:29 +08:00
小项目无所谓,多人项目要做好被喷的准备。
crist
2020-03-19 11:27:46 +08:00
你这是在瞎搞!
bk201
2020-03-19 11:28:06 +08:00
主键和业务相关,问题很多。
bk201
2020-03-19 11:32:20 +08:00
@heyjei 你那是数据宽表,基本不会做修改删除操作。
gamexg
2020-03-19 11:34:39 +08:00
我碰到过没有主键的...
xiaowangge
2020-03-19 11:34:54 +08:00
阿里巴巴《 Java 开发手册》

[强制]
表必备三字段:id, create_time, update_time。

说明:
其中 id 必为主键,类型为 bigint unsigned、单表时自增、步长为 1。
create_time, update_time 的类型均为 datetime 类型



https://github.com/alibaba/p3c/blob/master/%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4Java%E5%BC%80%E5%8F%91%E6%89%8B%E5%86%8C%EF%BC%88%E5%8D%8E%E5%B1%B1%E7%89%88%EF%BC%89.pdf
ajaxfunction
2020-03-19 11:35:25 +08:00
典型的小学生
好奇写法

而且代码变量名还能用中文呢, 没想到吧.jpg
passerbytiny
2020-03-19 11:38:41 +08:00
@tabris17 #27 你的理解完全反了,顺序主键提高的是 select 效率,但降低 insert 效率。随机写入不需要寻址,不需要考虑重复、乱序、并发等问题,明显要比顺序写入快。

@wangbenjun5 你的理解也反了,单列(字段)主键,从来都不是数据库设计或者数据库范式的要求,而是程序业务设计或者性能优化(更多的是后者)的要求,数据库范式甚至都没要求必须有主键。业务设计上要求单字段主键也是被逼无奈的被动要求。不管是为了识别还是关联,对象总得有 ID ;单字段 ID 明显比多字段复合 ID 舒服多了; ID 不能轻易修改:所以业务设计就给了个不成熟的规范:对象必须有一个业务无关的单字段 ID。这个规范有一个缺点,不是多了个字段,而是对象原本业务相关的自然 ID 被掩盖掉了。总归来说,加一个业务无关 ID,优点大于缺点,所以这个规范就这么用下来了。但是要记住这是程序设计规范,不是数据库设计规范。
rooob1
2020-03-19 11:48:34 +08:00
@littleylv 不要局限于这个例子
passerbytiny
2020-03-19 11:50:26 +08:00
@xiaowangge #44 一刀切 /懒政规范,就别搬出来了,徒让人笑话。举几个例子:用户表的主键叫做 user_id 是不是违反规范;是用 create_time 同时表示注册时间和记录创建时间,还是用 register_time、create_time 分别表示注册时间、记录创建时间;历史记录类型数据只插入不更新,放个 update_time 字段是不是脱裤子放屁。
assad
2020-03-19 12:09:16 +08:00
不想要主键的人,想啥呢
sadfQED2
2020-03-19 12:09:28 +08:00
@tant 补充一点,如果没有显示定义自增 id,会自动选择第一个不含空值的唯一索引当主键。但是这个也没有的时候,MySQL 应该会自动生成一个隐藏的自增字段当主键
tabris17
2020-03-19 12:17:31 +08:00
@passerbytiny 抱歉,你的理解才是有问题的。

我才你可能是想说顺序写入在高并发的情况下会引发热点造成性能问题。
排除这种极端情况,随机写入导致的拆分页操作才是真正的性能灾难
Norie
2020-03-19 13:07:19 +08:00
@loading age 难道不是每天一次
love
2020-03-19 13:10:11 +08:00
复合主键也是主键,也挺常用,比如用在关联表中。
只是在你这里的 name+age 不适合而已。
encro
2020-03-19 13:20:31 +08:00
innodb 没有主键,插入速度慢。

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

https://www.v2ex.com/t/654133

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

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

© 2021 V2EX