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