MySQL的Schema设计

对于基于性能的数据库Schema设计,我们并不能完全以规范化范式理论来作为唯一的指导。在设计过程中,应该从实际需求出发,以性能提升为根本目标来展开设计工作,很多时候为了尽可能提高性能,我们必须做反范式设计。

一、高效的模型设计

1、适度冗余-让Query尽两减少Join
数据库的规范化理论其实质是在概念上的单一化,虽然规范后的数据库中的表一般都较小,使表中相关列最少。这虽然可能在某些情况下增强了数据库的可维护性,但在系统要完成一些数据的查询检索时,可能要用复杂的Join才能实现,这势必会造成查询检索的性能低下。如果我们通过拆分Join,通过多次简单的查询来在应用中实现Join逻辑,那所带来的网络开销将会是非常巨大的。

2、大字段垂直分拆-summary表优化
大字段垂直拆分策略相对于前面介绍的适度冗余策略在做法上可以说差不多是完全相反的做法。适度冗余策略是将别的表中的字段拿过来在自己身上也存一份数据,而大字段垂直拆分简单来说就是将自己身上的字段拆分出去放在另外(单独)的表里面。

而我们将大字段拿出去,也是将一些我们在大部分查询中并不需要使用该字段的时候才会拿出去。而且,在我们拿出去之前,我们肯定会通过全面的评估比较之后才能做出拆分出去的决定。

3、大表水平分拆-基于类型的分拆优化
在很多大型的应用中,由于数据量非常庞大,并发访问又非常高,到达单台主机都无法支撑单个表的访问的时候,常常会通过这种大表的水平拆分,存放在多台主机的多个数据库中实现整体扩展性的提升。

4、统计表-准实时优化
为什么要准实时?
为什么要改变需求将“可以实时”的统计信息做成准实时的呢?原因很简单,因为实时统计的性能消耗成本太高。因为每一次展示(也就是每一次刷新页面)都需要进行统计计算,带来大量的重复资源浪费。而做成准实时的统计信息之后,我们每次只需要访问很小的数据量即可,不需要频繁的统计计算的工作。

什么类型的统计信息适合通过准实时统计表来优化实现?
首先,统计信息的准确性要求并不是特别的严格;
其次,统计信息对时间并不是太敏感;
再次,统计信息的访问非常频繁,重复执行较多;
最后,参与统计数据量较大;

二、合适的数据类型

1、优化数据类型提高性能的主要原理在于以下几个方面:
1)通过选用更“小”的数据类型减少存储空间,使查询相同数据需要的IO资源降低;
2)通过合适的数据类型加速数据的比较;

我们可以看出哪种类型占用的存储空间大,哪种占用的空间小。这样,在数据类型选择的时候,我们就可以结合各种类型的存储范围以及业务中可能存在的数据作出对应,然后选择存储空间最先的类型来使用。

2、CHAR类型
CHAR类型的存储特点是不管我们实际存放多长数据,在数据库中都会存放M个字符,不够的通过空格补上,M默认为1。虽然CHAR会通过空格补齐存放的空间,但是在访问数据的时候,MySQL会忽略最后的所有空格,所以如果我们的实际数据中如果在最后确实需要空格,则不能使用CHAR类型来存放。

3、VARCHAR类型
属于动态存储长度类型,仅存占用实际存储数据的长度。

4、TINYTEXT,TEXT,MEDIUMTEXT和LONGTEXT这四种类型同属于一种存储方式,都是动态存储长度类型,不同的仅仅是最大长度的限制。

三、规范的对象命名
对于数据库对象的命名规范其实可以很简单,而且业界也并不存在一个严格的统一规定,只需要在一个公司内足够统一基本就可以了。

1、数据库和表名应尽可能和所服务的业务模块名一致
这样,在DBA维护相关数据库对象的时候,新开发人员程序开发过程中,相关技术(或非技术)人员整理业务逻辑和数据关系的时候,都能够非常容易理解其中的关系。

2、服务于同一子模块的一类表尽量以子模块名(或部分单词)为前缀或后缀
对同类功能的表增加前缀或者后缀,也是让查看使用该表的各类人员能够很快的根据相关对象的名称就联想到相应的功能,以及相关业务。不论是从维护角度,还是从使用角度来看都会带来非常大的便利性。

3、表名应尽量包含与所存放数据相对应的单词
这对于新员工来说尤其重要,要想尽快的熟悉数据,尽快了解相关业务,快速的定位数据库中各表对应的数据意义是非常有帮助的。

4、字段名称也尽量保持和实际数据相对应
每个表都会有很多的字段对应数据的各种不同属性,要搞清楚各自代表的含义,除了完整规范的说明文档之外,命名清晰合理的字段名也是一个有用的补充,而且更为直接。

5、索引名称尽量包含所有的索引键字段名或者缩写,且各字段名在索引名中的顺序应与索引键在索引中的索引顺序一致,且尽量包含一个类似于idx或者ind之类的前缀或者后缀,以表名其对象类型是索引,同时还可以包含该索引所属表的名称。
这样做最大的好处在于DBA在维护过程中能够非常直接清晰的通过索引名称就了解到该索引大部分的信息。

6、约束等其他对象也应该尽可能包含所属表或其他对象的名称,以表名各自关系

四、小结
“数据库系统的性能不是优化出来的,更多的是设计出来的”。数据库Schema的设计并不如很多人想象的那样只是一个简单的对象对应实现,而是一个系统工程。要想设计出一个既性能高效又足够满足业务需求,既逻辑清晰又关系简单的数据库Schema结构,不仅仅需要足够的数据库系统知识,还需要足够了解应用系统的业务逻辑。