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