在大家开发的时候,很多时候不是说,有人告诉你已经完全的设计好数据库了,也没有专门的人去管理数据库表设计这块的内容,而阿粉的朋友就是这么悲催,接手了公司一个同事的一个比较重要的功能,而阿粉的朋友也没有重新进行设计,于是就出现了这样的一幕。
你设计的这是啥?
领导:你数据库设计的软删除呢?Delete 就直接给我删了?万一到时候用户反悔了,想查询某项数据怎么办?
我:........(内心OS:这特么不是我设计的好不)
领导:你赶紧给我加上这个,我给你讲讲需求,你看他之前做了多少了,把没做的功能都给我补上。
我:.........好的(内心OS:我擦,他做了这么久的功能就做了这么一丢丢,你让我抓紧时间做完,你是傻子么?)
领导:你看这,两个表的关联字段,竟然不是相同类型的,你不用相同的名字就不用吧,你类型不一样,怎么能行,你赶紧去统一一下。
我:.........(这明明不是我设计的表好不好,这种低智商的行为,是我能干出来的事情么?)
但是阿粉朋友在向阿粉抱怨的时候,就表示心态已经被影响了,明明不是自己的锅,结果这锅到最后全都是自己来背,不过想想也是,毕竟如果要是这个功能非常好做的话,那同事为啥辞职。阿粉接下来就说说这个数据库表的设计,到底是怎么设计才能更好呢?
数据库表设计遵循原则
数据库表设计范式
(1). 第一范式(确保每列保持原子性)
这是什么意思呢?你如果去百度上搜索,结果就是所有字段值都是不可分解的原子值。就这话,云里雾里的有点难理解呀,这种情况我们就得自己去想想有没有什么现实生活中的案例,比如说,我们在保存某些地址信息的时候,一般我们都是采用,省市区,然后再加上具体的位置来表示完整的地址,很少有人会在数据库中直接设计一个地址的字段,再比如我说我们设计商品的时候,都是商品,数量,价格,而不是设计成商品1,商品2,商品3,数量1,数量2,数量3.
而数据库的第一范式也就是 1NF,实际上不单单是保证每一列的原子性,还有如果两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据。
这就是阿粉上面说的那个商品的案例。
(2).第二范式
在一个数据库表中,一个表中只能保存一种数据,不可以把多种数据保存在同一张数据库表中。
每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。
上面这句话感觉好像有点多此一举的样子,相同的数据信息在一般人的设计中,是不会出现在同一张表中的,因为毕竟如果某些字段一直是重复的,数据量多不说,关联的时候也会出现左也不行,又也不行,就会出现写SQL出现各种问题的情况。
(3).第三范式
数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系。阿粉之前接收过一个项目,就是出现了 A 指向 B,B 指向 C,加入说我们现在有一张订单表,我们订单表中肯定要有人员的信息,而我们又会有一张人员信息表中的Id与订单表中的人员信息对应,这时候,订单表中就尽可能的不要存在人员的其他相关的信息了,比如说姓名,身份证号,等等信息。
而这时候,我们在获取订单信息的时候,直接通过当前用户的ID,就可以查询出所有对应的订单,那些所有的人员信息全部都包含在了人员信息表中。
说到这里,阿粉实际上想说,数据库三范式,只是说是一个原则,而不是非要遵守的原则,因为有些时候,很多在建表的时候,都是根据我们的需求来进行制定。
范式也有优缺点:
设计数据表的时候,其实范式的优点很明显,避免数据冗余,减少维护数据完整性的麻烦,减少数据库的空间,数据变更速度快
但是缺点也是一样的明显,按照范式的规范设计的表,等级越高的范式设计出来的表数量越多,获取数据时,表关联过多,性能较差。
阿粉之前见过一个很早之前的项目,一个医疗系统,设计的表大概超过有2000个表,阿粉当时都满脸的震惊。
据说是一个很早之前的程序员设计的,当时是严格遵守了范式来进行的数据库的设计,结果可想而知。一个SQL查询,关联那么多的表,效率能高到哪里去呢?
学会通过需求来进行定制
大家还记得阿粉之前写过的用UUID生成主键,被diss么?
比如之前的对比,数据库自增,雪花算法生成ID,和UUID生成ID,这三个的对比,结果100w条数据,最终胜出的还是雪花算法,大家对这个有兴趣的可以去看一下这篇文章。
使用uuid作为数据库主键,被技术总监怼了一顿!
为什么说要学会通过需求来进行定制,因为首先我们要清楚,你写的东西,最后实际的落脚点,都是需求,实现了这个需求,在不出现任何意外的情况下,永远都是需求放在第一位,如果你把一个简单的一对多的关系,非要拆分成一个多对多的关系,这完全就是多此一举的事情。
而这种通过需求来进行定制的,实际上就可以称之为反范式。
而反范式设计同样的也是优缺点明显,业务场景中需要的数据几乎都可以在一张表上显示,数据冗余了。
但是它提高了业务响应的时间,现在为什么有些中间件的存在,就是因为随着公司业务的拓展,数据量的增多,有时候一个表中的数据超过百万,甚至千万,当你写一个NOT IN 的时候,你就会发现,一秒,两秒,三秒....时间就这么过去了。
阿里开发手册
实际上阿粉之前也专门研究过一段时间的阿里开发手册,比如:
【强制】:表达是否概念的时候,必须使用is_xxx的方式来进行命名,数据类型使用unsigned tinyint (1,表示是,0表示否)
比如如果你在数据库的表中设计软删除的概念,你选择使用is_delete 还是会选择使用 deleted 这种,实际上百分之60以上的是会使用 is_delete,而设计这种 deleted 的,一般很多都是刚入行不久的年轻人,对字段设计没有什么概念的。
【强制】:表名称不使用复数名词,比如说我们的活动Activity,你如果把它设计Activities,当你在建立实体类的时候 Activity 和 Activities 是不是感觉就不一样,第二个看着就总是有些难受。
大家如果有兴趣的,可以在公众号回复 阿里 获取泰山版 阿里巴巴开发手册。
关于数据库设计,你还想知道些什么?