前言
在讲范式和反范式之前,首先先搞清楚什么是范式!如下
第一范式
每个表的每一列都要保持它的 原子性 也就是表的每一列都是不可分割的
修改后
第二范式
要在满足第一范式的基础上,每个表都要保持 唯一性 也就是表的非主键字段要完全依赖主键字段。
第三范式
要在满足第一和第二范式的基础上,表中不能产生传递依赖,要消除表中的冗余性
范式
范式优点
- 范式化的更新操作通常比反范式操作要快
- 当数据较好的范式化时,就只有很少或者没有重复数据所以只需要修改更少的数据
- 范式化的表通常很小,可以更好的放在内存中,所以执行操作会更快
- 很少有多余的数据意味着检索列表数据时更少需要DISTINCT或者GROUP BY语句
范式缺点
范式话通常需要关联,稍微复杂一些的查询语句在符合范式上可能需要至少一次关联,或许更多,这不但代价昂贵,也可能是的一些索引策略失效!例如:范式化可能将列放在不同的表中,而这些列如果在一个表中本可以属于同一个索引!
反范式
反范式话数据都在同一张表中,这样可以很好的避免表关联,这样可以避免导致索引失效的一些问题,单表可以使用更有效的索引策略,例如:有个网站,允许付费用户发消息,现在先查看付费用户发送的最近10条消息,如果范式话的结构并且索引了发送日期字段published,这个查询也许看起来像这样
更有效的执行这个查询,MySQL需要扫描message表中的published字段的索引,对于每一条匹配到的数据都需要到user表里检查这个用户是不是付费用户,如果只有一小部分用户是付费用户,那么这是效率底下的做法,如果采用反范式的话,将两张表的字段合并下,并且增加一个索引(account_type,published),就可以不通过关联写出这个查询,如下
混用范式和反范式
事实上完全范式和反范式这种设计,只有实验室里才有的,在实际应用中通常会混用,可能使用部分范式话的设计,缓存表,以及其他技巧。