淘宝数据库表设计20张表以上(淘宝数据库表设计软件)这都可以

 2022-11-09    15  

MySQL数据库构架设计的底子是对表结构的设计。

如对表头类型的优先选择;表的储存设计,填充还亦然填充,如何换用填充算法;表的出访设计,SQL还是NoSQL。

这些问题貌似十分简单并容易提问,不过绝大部分的标准答案看似错的。

这类错的吓人的标准答案还在网路上日复一日的广为流传着,甚至还成为了简而言之的MySQL赵雄。

其中,两个最明显的错误是关于MySQL的换行符设计。

绝大部分人的提问如此自信:用8二进制的 BIGINT 做换行符,而不要用INT。

这种的提问,只站在了数据库这几层,而没有从业务的视角思索换行符究竟什么

换行符是两个自增ID么?

站在2021年的时间当今社会,用自增做换行符,构架设计上可能连不及格分都拿不到。

自增ID的问题

自增ID做换行符,简单简练,几乎所有数据库都全力支持自增类型,只是实现上各别略有不同罢了。

自增ID除简单,其他都是优点,整体来看存有下列几方面的问题。

具体来说,安全性不高。存有自增ID追述的问题,这个问题直至新一代版的MySQL 8.0才复原。

其二,安全性不高。对内曝露的USB能十分容易揣测相关联的信息。

比如说/User/1/这种的USB,能十分容易揣测用户ID的值为啥,总用户数目有啥,也能十分容易地通过USB进行数据的爬取。

另外容易被忽略了的一点儿是,自增ID的操控性极差,需要在数据库服务器端聚合。

而且业务还需要附加继续执行一场类似于last_insert_id()的表达式就可以知道这边填入的自产品服务,这需要多一次的互联网可视化。

在海量数据mammalian的系统中,多1条SQL,就多一场操控性上的开支。

最后也是最重要的一点儿是,自增ID是局部性惟一,只在现阶段数据库示例中惟一,而不是自上而下惟一,在任一服务器间都是惟一的。

对目前分布式系统来说,这简直是噩梦。

淘宝的换行符设计

在淘宝的电商业务中,订单服务是两个核心业务。

那么请问,订单表的换行符淘宝是如何设计的呢?是自增ID么?

打开淘宝,看一下订单信息:

淘宝数据库表设计20张表以上(淘宝数据库表设计软件)这都可以 值得看韩国电视剧 韩国电视剧 电视剧推荐 百科资讯 第1张

从上图能发现,订单号不是自增ID!!!

接着,我们详细看下上述4个订单号:

1550672064762308113

1481195847180308113

1431156171142308113

1431146631521308113

注意到了什么没?订单号是20位的长度,且订单的最后6位都是一样的,都是308113。

此外,订单号的前面14位部分是单调递增的。所以,我大胆揣测,淘宝的订单ID设计应该是:

订单ID = 时间 + 去重表头 + 用户ID后6位尾号

这种的设计能做到自上而下惟一,且对分布式系统查询及其友好。

换行符的设计

看到这里,姜老师想说的是自增ID只适合用于非核心业务,如告警、日志、监控等信息。

对核心业务表,换行符设计至少应该是自上而下惟一且是单调递增。自上而下惟一保证在各系统之间都是惟一的,单调递增是希望填入时不影响数据库操控性。

这里姜老师推荐最简单的一种换行符设计:UUID。

我知道很多同学会说:UUID啊,虽然自上而下惟一,但是占用36二进制,数据无序,填入操控性差。

在得到上述结论前,是不是应该先提问下列这种问题呢?

为什么UUID是自上而下惟一的? 为什么UUID占用36个二进制? 为什么UUID是无序的?

好吧,接着姜老师来手把手的给你讲解UUID。

MySQL数据库的UUID实现是Version 1的版实现,其组成如下所示:

UUID = 时间低(8二进制)- 时间中高+版(8二进制)- 时钟序列 - MAC地

为了更为详细的讲解UUID的实现,我们以UUID值e0ea12d4-6473-11eb-943c-00155dbaa39d举例,其具体组成如下图所示:

淘宝数据库表设计20张表以上(淘宝数据库表设计软件)这都可以 值得看韩国电视剧 韩国电视剧 电视剧推荐 百科资讯 第2张

在UUID中他的时间部分占用60位,储存的类似于TIMESTAMP的时间戳,但表示的是从1582-10-15 00:00:00.00到现在的100ns的计数

能看到UUID储存的时间精度比TIMESTAMPE更高,时间维度发生重复的概率降低到1/100ns。

时钟序列是为了避免时钟被回拨导致产生时间重复的可能性。MAC地址用于自上而下惟一。这提问了为什么UUID能是自上而下惟一的问题。

UUID根据字符串进行储存,设计时还带有无用"-"字符串,因此总共需要36个二进制。

最后,为什么UUID是随机无序的呢?

因为UUID的设计中,将时间低位放在最前面,而这部分的数据是一直在变化的,并且是无序!!!

若将时间高低位互换,则时间是单调递增的了,也就变得单调递增了。

MySQL 8.0解决了UUID存有的问题,除去了UUID字符串中无意义的"-"字符串,并且将字符串用二进制类型保存,这种储存空间降低为了16二进制。

更重要的是,他能更换时间低位和时间高位的储存方式,这种UUID是有序的UUID了。

能通过MySQL8.0提供的uuid_to_bin表达式实现上述功能,同样的,MySQL也提供了bin_to_uuid表达式进行转化:

淘宝数据库表设计20张表以上(淘宝数据库表设计软件)这都可以 值得看韩国电视剧 韩国电视剧 电视剧推荐 百科资讯 第3张

所以,现在起能通过表达式uuid_to_bin(@uuid,true)将UUID转化为有序UUID了。

自上而下惟一 + 单调递增,这不是我们想要的换行符实现么?

BTW,8.0之前的版没有提供这两个表达式,有聪明的小伙伴知道怎么实现么?欢迎留言

有序UUID操控性测试

16二进制的有序UUID,相比之前8二进制的自增ID,操控性和储存空间对比究竟如何呢?

我们来做两个测试,填入1亿条数据,每条数据占用500二进制,含有3个二级索引,最终的结果如下所示:

淘宝数据库表设计20张表以上(淘宝数据库表设计软件)这都可以 值得看韩国电视剧 韩国电视剧 电视剧推荐 百科资讯 第4张

从上图能看到填入1亿条数据有序UUID是最快的,而且在实际业务使用中有序UUID在业务端就能聚合。还能进一步减少SQL的可视化次数。

另外,虽然有序UUID的相比自增ID多了8个二进制,但实际只增大了3G的储存空间。

储存空间的增大并没有小伙伴想象中的那么大。

总结

在当今的互联网环境中,十分不推荐自增ID作为换行符的数据库设计。

更推荐类似于有序UUID的自上而下惟一的实现。

另外在真实的业务系统中,换行符还能加入业务和系统属性,如用户的尾号,机房的信息等。

这种的换行符设计就更为考验构架师的水平了。

原文链接:https://zazhiba.com.cn/post/25410.html

=========================================

https://zazhiba.com.cn/ 为 “自由随风” 唯一官方服务平台,请勿相信其他任何渠道。