数据库范式与反范式设计,是一门艺术
我是架构精进之路,点击上方“关注”,坚持每天为你分享技术干货,私信我回复“01”,送你一份程序员成长进阶大礼包。
前言
在日常业务研发过程中,常常需要与数据库表打交道。范式是数据表设计的基本原则,对于数据表的设计范式,我们特别容易忽略它的存在。常常很多时候,当数据库运行了一段时间之后,我们才发现数据表设计得有问题。然后重新调整数据表的结构,就需要做数据迁移,还有可能影响程序处理的业务逻辑,以及系统的正常服务运行。
其实在数据库表结构设计的初期时候,我们就需要重视数据表的设计。
数据库的设计范式
数据库的设计范式包括哪些呢?
我们在设计关系型数据库模型的时候,需要对关系内部各个属性之间联系的合理化程度进行定义,这就有了不同等级的规范要求,这些规范要求被称为范式(NF)。
范式简单理解即为:一张数据表的设计结构需要满足的某种设计标准的级别。
目前关系型数据库一共有 6 种范式,按照范式级别,从低到高分别是:1NF(第一范式)、2NF(第二范式)、3NF(第三范式)、BCNF(巴斯 - 科德范式)、4NF(第四范式)和 5NF(第五范式,又叫做完美范式)。
数据库的范式设计越高阶,冗余度就越低,同时高阶的范式一定符合低阶范式的要求,比如满足 2NF 的一定满足 1NF,满足 3NF 的一定满足 2NF,依次类推。
那这么多范式是不是都要掌握呢?
一般来说数据表的设计应尽量满足 3NF。但也不绝对,有时候为了提高某些查询性能,我们还需要破坏范式规则,也就是反规范化。
范式设计
范式化模型要求满足下面三大范式:
1NF(第一范式)指的是数据库表中的任何字段属性都是原子性的,不可再分。
这种情况比较好理解,我们在设计某个字段的时候,对于字段 X 来说,就不能把字段 X 拆分成字段 X-1 和字段 X-2。
2NF(第二范式)指的数据表里的非主属性都要和这个数据表的候选键有完全依赖关系。
假设存在用户、商品两个数据模型
用户模型的主键是用户 ID,那么用户模型其它字段都应该依赖于用户 ID
商品模型的主键是商品 ID,它和用户没有直接关系,则这个属性不应该放到用户模型,而应该放到“用户-商品”相关联的订单表中去。
3NF(第三范式)在满足 2NF 的同时,模型非主键字段不能相互依赖。
例如:订单表(订单 ID,商品 ID,用户 ID,用户姓名)
初看该表没有问题,满足第二范式,每列都和主键列“订单编号”相关。再细看你会发现“用户姓名”和“用户 ID”相关联,“用户 ID”和“订单 ID”又相关联,最后经过传递依赖,“用户姓名”和”订单 ID”相关联。为了满足第三范式,应去掉订单表中“用户姓名”列,放入用户表中。
总结一下:
1NF 需要保证表中每个属性都保持原子性;
2NF 需要保证表中的非主属性与候选键完全依赖;
3NF 需要保证表中的非主属性与候选键不存在传递依赖。
反范式设计
尽管前面我们介绍了数据表的设计有很多范式,数据库设计范式越高阶,数据表就会越精细,数据的冗余度也就越少,在一定程度上可以让数据库在内部关联上更好地组织数据。但事实上,我们在设计数据表的时候却不一定要一定严格参照这些标准,有时候我们也需要采用反范进行优化,通过空间来换取时间。
既然范式是为了消除冗余,那么反范式就是通过增加冗余、聚合的手段来提升性能。
反范式就是相对范式化而言的,换句话说,就是允许少量的冗余,通过空间来换时间。同时反范式优化也是一种改善慢查询的优化思路。
例如:上面用户、商品、订单表的例子
我们可以在订单表中冗余商品名称字段,这样我们可以通过用户关联查询到订单表之后,无需再次关联商品表而拿到商品名称。如:订单表(订单 ID,商品 ID,用户 ID,商品名称)
反范式设计存在的问题
从上面的例子中可以看出,反范式设计可以通过空间换时间,提升查询的效率,但是反范式也会带来一些新问题。
主要问题包括:
在数据量小的情况下,反范式不能体现性能的优势,可能还会让数据库的设计更加复杂;
比如采用存储过程来支持数据的更新、删除等额外操作,很容易增加系统的维护成本。
反范式设计适用场景
那么反范式优化适用于哪些场景呢?
在现实工作中,我们经常需要一些冗余信息,比如订单中的收货人信息:用户姓名、手机号码以及收货地址等等。
其实每次发生的订单收货信息都属于历史快照信息,需要进行保存,但同时用户又可以随时修改自己的信息,这时保存这些冗余信息是非常有必要的。
结论:当冗余信息有价值或者能大幅度提高查询效率的时候,我们就可以采取反范式的优化。
总结
在日常我们的工作当中,需要遵守一定的规范,例如项目研发流程规范、项目汇报规范以及会议规范等等,这些规范虽然会叫人感觉存在一定的约束感,所以我们常常对规则加以调整灵活运用,这样可以保证工作的正确性和效率的保障性。
其实这与数据表的设计规范很像,我们既需要规范性,同时也要考虑到执行时的方便性。
范式设计与反范式设计堪称 一门设计 “艺术”,因为它没有标准答案...
范式本身没有优劣之分,只有适用场景不同。没有完美的设计,只有合适的设计,我们在数据表的设计中,还需要根据需求将范式和反范式混合使用。
系列推荐:
MySQL explain 中的 rows 究竟是如何计算的?
- END -
作者:架构精进之路,专注软件架构研究,技术学习与个人成长,关注并私信我回复“01”,送你一份程序员成长进阶大礼包。
Thanks for reading!
版权声明: 本文为 InfoQ 作者【架构精进之路】的原创文章。
原文链接:【http://xie.infoq.cn/article/4c2918bb030569186d82ba590】。文章转载请联系作者。
评论