有一小阵子没有更新技术文章了,今天咱们继续MySQL系列,今天要说的是MySQL表结构设计。在个人工做经历当中,就踩过不少这方面的坑,在以前的文章《MySQL表设计踩过的坑!》中,也谈到了一些坑,但总有一种,只是指出了问题,却没有给出解决方案的感受,今天咱们就来说讲MySQL表如何设计才能避免踩坑。数据库
在表结构设计中,首先咱们就要选择一个合适的存储引擎,咱们在以前的文章《谈谈MySQL存储引擎》就简述了每一个存储引擎的区别,在选择存储引擎时,咱们应该根据本身的业务场景来选型存储引擎,如:须要OLTP(在线事务处理)的应用,就应该选择InnoDB存储引擎,若是仅仅用做存储数据,容许数据不一致,数据仓库等场景时,可用MyISAM存储引擎,若是你不知道如何选择,那么使用InnoDB存储引擎就对了。微信
这里以前也说过一次了,主要是为了保存emoji表情,例如: 微信昵称,就有不少带有emoji表情的,这里咱们使用utf8mb4字符集,千万不要使用blob类型来存储。架构
众所周知,主键的设定是很是重要的,在主键的选择上,应该知足如下几个条件:性能
惟一性 (必要条件)spa
非空性.net
有序性设计
可读性3d
可扩展性code
主键的惟一性和非空性,就很少说了,其中有序性就有很多好处。例如: 查询时,为有序IO,就可提升查询效率,存储的顺序也是有序的,往远了看,分库分表也是有好处的。所以,我建议使8字节无符号的bigint(20)做为主键的数据类型
以下:中间件
create table t_base_user( id bigint(20) unsigned not null primary key auto_increment; .... )
这里有几个注意点:
主外键的数据类型必定要一致!
每一个表中的主键命名保持一致!
(我就吃过这种细节上的亏)。
无符号与有符号的区别:
有符号容许存储负数,无符号只容许从正数,无符号最小值为0,最大值根据类型不一样而不一样。
如下为各个int类型的范围:
问题一: 为何不使用varchar类型做主键
答: varchar类型会对性能有影响,其中varchar也不是有序的,可读性也很差,这里不建议使用。
(以前我就用过UUID做为主键,可读性简直了….当时数据量较小,还感受不到性能)。
PS: 主键实际上是一个比较大的话题,为何这么说呢,其实上面的方案也是有缺点的,适用于主从架构,对于多主呢?此时的主键是否是就会有重复的状况产生了,这也就是为何一些大厂有本身的ID生成中间件的缘由了,这里不作深刻讨论,咱们下次单独写一篇文章来讲。
外键约束用来保证数据完整性的,这一点我很赞同,可是我不建议在数据库表中加外键约束,由于在数据表中添加外键约束,会影响性能,例如: 每一次修改数据时,都要在另外的一张表中执行查询。个人建议是:在应用层,也就是代码层面,来维持外键关系。
这里指的是数据列的数据类型,在选择合适的数据类型时,咱们应知足如下条件:
尽可能选择小,简单的数据类型。
保持可读性。
尽可能避免Null
咱们尽量选择小的数据类型,这样会有不少好处,好比服务端处理效率,传输等都会快些。这里给出几个常见的数据类型设计:
状态类型用 tinyint,例如 性别等。
时间日期使用datetime,timesamp类型,我比较喜欢使用datetime类型,(可读性高些)。
尽可能不要使用text和blob数据类型,特别是blob,
这个字段主要用做业务上的逻辑删除,在如今数据为金的时代,数据不建议作物理删除。缘由有如下几点:
可恢复,物理删除一旦删除,即不可恢复。
逻辑删除数据可用数据分析等。
例如:
deleted tinyint not null default 0;
这些主要是用做业务上的字段,每一个表中都应该有,在查询,以及问题查找定位时有诸多好处,例如: 查询最近三个月的登陆用户,这时就可用建立时间来查询等等,
如:
created_time datetime not null default now(); updated_time datetime not null default now() comment ''
索引说过不少次了,这里就再也不详细说了,可参考以前的文章《写会MySQL索引》,这里须要强调的是:我建议在建立时间上都加上索引。
添加注释,这是很是重要的,其中包括表注释,字段注释。主要是为了后期表结构的维护,我相信你对着数据表中那么多字段,若是没有注释的话,你是很难一会儿明白是什么意思的,即便你是该表结构的设计者,十天半个月过去后,你还记得吗?
简单实例:
create table t_base_user( id bigint(20) UNSIGNED not null primary key auto_increment comment "主键", name varchar(50) character set utf8mb4 comment "", created_time datetime not null default now() comment "建立时间", updated_time datetime not null default now() comment "修改时间", deleted tinyint not null default 0 comment "逻辑删除 0正常数据 1删除数据" )engine=innodb charset=utf8 comment "用户表"; //添加索引 alter table t_base_user idx_created_time(created_time);
以上表结构仅做演示,实际表结构设计时,会更复杂些,但思路是同样的。
下面精简一下:
选择合适的存储引擎,通常使用InnoDB。
选择合适的字符集,无emoji使用utf8,有emoji使用utf8mb4。
主键使用bigint(20),主外键类型一致。
选择合适的类型。
添加逻辑删除,建立,修改时间。
添加表,字段注释
添加索引
以上是表结构设计时的一些注意事项,能够说是我在MySQL表结构设计的一点点积累吧,在这里抛砖引玉了,有不一样意见的小伙伴,均可在留言区留言,咱们旨在设计好一个不给本身挖坑的表结构。
相关阅读:
扫码关注,一块儿进步
我的博客: http://www.andyqian.com