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