比如:
用户表中,将用户邮箱+密码的值去做 MD5,得出来的值作为 userId
订单表中,将订单数据+时间戳的值去做 MD5,得出来的值作为订单 Id
主要的疑问是,32 位的 id 是否过于占用空间?
以及其他缺点希望各位 V 友能发表下看法。
比如:
用户表中,将用户邮箱+密码的值去做 MD5,得出来的值作为 userId
订单表中,将订单数据+时间戳的值去做 MD5,得出来的值作为订单 Id
主要的疑问是,32 位的 id 是否过于占用空间?
以及其他缺点希望各位 V 友能发表下看法。
|
TakamineMay 5, 2020 via Android
1
……这样做的意义是什么,强行想让主键 id 和业务含义关联起来吗。
|
|
ajaxfunctionMay 5, 2020
2
要是用户密码改了呢? 之前生成的 userid 和现在的 userid 不一样,系统不就乱了吗?
简单的问题复杂化了啊! |
|
creedowlMay 5, 2020 via Android
3
要是用户改密码怎么办,如果是想要隐藏真实 id 可以用 hashid
订单可以用雪花算法 |
|
nvkouMay 5, 2020 via Android
5
uuid 也是这么做的。只不过人家用一去不回头的时间做种子之一。
没有必要重复发明轮子 |
|
6
|
|
luopengfei14May 5, 2020
7
用户一旦修改邮箱、密码,你就找不回来 userId,而且 md5 生成的 userId 对索引不友好。
简单点直接用自增 id 当作 userId,考虑多的可以用雪花算法生成 userId,一般够用。 还有 md5 、uuid 字符串理论上避免不了重复的可能 |
|
yukilohMay 5, 2020
8
用户登陆用账号行不,手机行不,你要做 3 个 userid 吗
|
|
9
@nvkou 倒也没有说想重复造轮子,不过确实没有想过直接调用已有的算法去生成,是个不错的方式
|
|
chendyMay 5, 2020
10
负载不大自增就够用了
至于 “32 位过于占用空间?”…emm ??? |
|
11
好吧,我的表达存在歧义,其实这个 userid 并不作为对外公开的值,也不提供给用户登录使用,只是内部对用户的一个标识,可以理解为就是用户表的主键 id
|
|
murmurMay 5, 2020
12
uuid 也比 md5 好啊,你的用户量多少,少的话可以,多的话得考虑下防装,你估计是看了 mongo 那个主键,别人是有算法的,可以保证在数据结构上的一些优化
|
|
14
@murmur 想请教一下防装是什么意思
|
|
changeProMay 5, 2020 via Android
16
“md5 生成的 userId 对索引不友好” 少误导其他人
|
|
wangyzjMay 5, 2020
17
不是不行, 百害无一利
|
|
changeProMay 5, 2020 via Android
18
首先,为什么要这样做?主键 ID 几乎都是 fixed length,磁盘内存、又便宜,索引不是问题。md5 也可以看作是 UUID,用 UUID 做主键大部分是为了解决分布式的一些问题,题主是为了折腾?
|
|
19
你这样做会严重影响插入性能,因为会频繁导致页分裂跟行移动,产生空间碎片
|
|
20
@changePro 我觉得没毛病啊
|
|
msg7086May 5, 2020 via Android
21
主键不与业务相关。你看看你的想法是否违反了这条惯例。
|
|
xuanbgMay 5, 2020
22
占空间倒没什么,现在存储这么便宜……
问题是: 1 、效率低,算一个哈希值也是有开销的。 2 、建立索引效率受影响。 然后,直接用 uuid 他不香吗? |
|
changeProMay 5, 2020
23
@Jacky23333 会导致性能下降,如果缓存不命中,导致大量磁盘 IO 。因为相同的数据,page 更多了。buffer pool 设计好的话的话,其实也还好
|
|
PopRainMay 5, 2020
24
如果不想用 uuid, 推荐 Twitter 雪花(SnowFlake)算法,一个 64 位整数
|
|
l3n641May 5, 2020
25
不建议这样做,主键越长 索引也占用空间.如果数据量大的话,添加和更新数据会很大影响性能.如果是 mysql 的 inodb 的话.其他的普通索引都会包含主键键值.这时候会更加占用空间.
|
|
saulshaoMay 5, 2020
26
通常情况下,主键字段就选择单纯的整数 /大整数 /无符号整数就行。
凡是需要某种业务相关计算来"产生"主键值的动作,都是花费很高并且没什么收益的方案。 |
|
yinzhiliMay 5, 2020
27
不建议。这样的订单号过长,且可读性几乎等于 0 。
|
|
PHPer233May 5, 2020 via Android
28
一个简单的 id 让你搞得这么复杂
|
|
yjxjnMay 5, 2020
29
雪花算法不香么?
|
|
joooooker21May 5, 2020
31
单体应用可以用自增主键
分布式应用可以用雪花算法或 uuid 你说的这种方法没有意义且消耗资源 |
|
xiangyuecnMay 5, 2020
32
设计 ID 结构最核心的一点,我觉得应当是时间粗略有序,uuid 、hash 都达不到时间粗略有序,参考楼上的雪花算法
你希望你的 id 排序之后是毫无规律的随机排序(似乎会影响插入性能), 还是按照插入顺序先后排序(也就是插入时间),普通自增 id 天然有序。id 里面用时间因子作为前缀妥妥的,后面随便拼上 uuid 、md5 之类的,就基本上时间粗略有序了 |
|
silvernooMay 5, 2020 via Android
33
md5 不是 128 位吗
|
|
Jacky23333May 5, 2020 via Android
34
@changePro 我是说你这句话 “-“md5 生成的 userId 对索引不友好” 少误导其他人”
|
|
Jacky23333May 5, 2020 via Android
35
@Jacky23333 我没觉得这句话误导他人了啊
|
|
jugeliziMay 5, 2020
36
似乎是 php 程序员
|
|
aflowMay 5, 2020
37
你这是在给后面埋坑,单体自增主键就好,md5 有重复的可能,不应该用来做唯一 id 。
不要自作聪明 |
|
v2GeekerMay 5, 2020
38
自增 id 好,这样建立的索引占用空间小,维护索引成本低,速度更快!
|
|
39
用户名 [email protected] 密码 forecast
用户名 [email protected] 密码 recast 所以还是乖乖用 UUID 吧。 另外,自增 id 和 UUID 可以同时用。主键自增,UUID 唯一约束。对外想用哪个就用哪个。 索引和存储空间的问题真不用担心。用户表邮箱、手机、用户名都有唯一约束,多一个也不见得会满。至于空间问题,最便宜的就是存储了…… |
|
n0tyetMay 6, 2020 via Android
40
把高性能 mysql 看完再继续思考
|
|
keenkillerMay 6, 2020 via Android
41
无意义,自增或者 snowflake
MySQL 的话别用 uuid |
|
MithrilMay 6, 2020
42
这么多人都没说到点子上。。
问题是 MD5 或者其它的摘要算法都是会冲突的啊。。。 算法设计目的是尽量阻止人为制造冲突,而不是完全没有冲突,毕竟只是摘要而已。小概率事件并不等同于不可能事件。 UUID 是直接在里面包含时间戳从而避免冲突的,你这个连时间戳都一块摘要了。。。 除非你自行设计了解决办法,不然完全不应该直接用 Hash 作为数据库主键。 |
|
icegreenMay 6, 2020
44
同意上面一位老哥的说法;
需要考虑你的数据库引擎以及索引结构, 以 mysql 的 innodb 来说, 主键无序,在插入的时候,会导致大量页分裂,降低索引效率; |
|
cheng6563May 6, 2020 via Android
45
非有序的主键对索引不太友好吧
|
|
zchlwjMay 6, 2020
46
MD5 可是会冲突的
|
|
securityCodingMay 6, 2020
47
不要把问题复杂化 , 直接使用雪花算法就行了
|
|
FelldeadbirdMay 6, 2020
48
雪花算法可以满足楼主的需求了。
|
|
tailfMay 6, 2020
50
主键使用这么长的字符串,确实会影响性能
|
|
lanterboyMay 6, 2020
51
19L 正解,如果楼主用的是 InnoDB 引擎,主键是聚簇的,乱序主键非常影响性能,建议把主键和业务唯一键分开,主键可以用雪花
|
|
inktigerMay 6, 2020
52
占用空间是肯定的,问题复杂化了也是肯定的,做之前先想想目的是什么,我是觉得一切根据自身原因来
|
|
tabris17May 6, 2020
53
|
|
14v45mJPBYJW8dT7May 6, 2020
54
主键 id 不要动,新建 user_id 字段唯一索引就能满足
|
|
55
1. MySQL innodb 主键是聚族索引,用 uuid / md5() / base58 / base64 等生成的无序串做主键,数据量增长后插入性能急剧下降
2. 可以选择主键使用 AUTO_INCREMENT 整数,新增一列存储 uuid 等无序串并加索引。不过大查询量下,性能肯定不如主键这种聚族索引,可以通过缓存解决 3. uuid 也不完全是无序串,毕竟它是基于时间戳生成的,按一定规则进行解构重组,也能变得“有序”,作为主键据说性能也还行 https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/ 4. snowflake 完美解决了所有问题 |
|
56
至于用 md5 还是 uuid,楼主自己觉得开心请随意选择。只要保证没有冲突就好。君不见 b 站现在都用变种 base56 了
|
|
HeebeMay 6, 2020
58
我想问下,MD5 是你想出来的,还是有人教你的?如果有人教你的,赶紧删除了他,因为他可能让你损失 1 个亿。
我猜楼主是想做成一个无法被人类读取的订单号,来防止别人猜测业务量? 这叫分布式 ID,随便搜索下就有一堆的方案。 |
|
CmdhelpMay 6, 2020
60
建议看一波 al 爪洼开发手册
|
|
3dwelcomeMay 6, 2020
61
@Mithril 主键重复,就对自身加盐 hash,变成第二个,第三个 hash,循环多试几次,最后总能插进去的。
查询也是同样操作,查出来数据需要二次校对,如果订单不对就进行二次 /三次查询。 当然这些都是有前提的,表数据量必须在可控范围内。万一数据一多,冲突越多,肯定没戏。 |
|
sujin190May 6, 2020
62
id 的话,感觉有顺序的更好一点吧,空间的感觉无所谓吧,反正内存磁盘也不值钱
|
|
MithrilMay 6, 2020
63
@3dwelcome 你这个前提是他不拿主键直接做查询,关键是既然不查询那为啥不直接自增 id 。。。
而且冲突就只是个概率,并不是真的可控,只是大概率不出问题。运气不好一直冲突也不是没可能的。 |
|
3dwelcomeMay 6, 2020
64
@Mithril 我也不知道楼主为啥放着自增长 ID 不用,要另辟蹊径。也许就是楼上有人猜测的,防止对数据库暴力查询。因为实在想不出,这样做有别的什么理由。
至于谈到冲突,以前测试过对 MD5 的散列分布图,图上来看还是挺均匀的。 |
|
cloudzhouMay 6, 2020
65
如果不使用自增 id 的话,uuid 不行吗? snowflake 也可以
|
|
jasondingMay 6, 2020
66
已经确认存在两个不同的值经过 MD5 运算后可能会导致结果一致,万一不幸碰上了你准备怎么处理
|