【一文秒懂】带你彻底搞懂范式与反范式数据库设计

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第1张图片

前言

我们经常听到范式设计与反范式设计,那么什么时候该遵循范式设计?什么时候又该违反他的规则呢?带着这两个问题,让我现在带你研究~

范式

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第2张图片
范式就是前辈通过不断的验证给到的为了建立冗余较小、结构合理的数据库,是设计数据库必须遵循的一定规则,在关系型数据库中这种规格叫做范式,本篇不仅说明范式设计,也会给到一些例子,带着各位一起分析给到的数据表设计属于第几范式。

1NF 第一范式

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第3张图片
遵循的规则:每一列属性都是不可再分的属性值,确保每一列的原子性

啥玩意是不再可分?例如用户名、性别、年龄联系方式则就是不能再分了。
但例如城市,北京市通州区,我们还是可以再分的,将一个字段分为省:北京市 区:通州区

首先,我们看到用户信息表中,所在城市是可以在进行细分的。
编码 用户名 年龄 性别 联系方式 所在城市
1 张三 18 1888888888 山东省青岛市
2 李四 17 1999999999 湖北省武汉市
3 王五 22 1777777777 山东省青岛市
下表我们根据上述用户信息表,将城市分为省和市两个字段,这样设计后,该数据表则符合了第一范式的要求。
用户编码 用户名 年龄 性别 联系方式 所在省 所在市
1 张三 18 1888888888 山东省 青岛市
2 李四 17 1999999999 湖北省 武汉市
3 王五 22 1777777777 山东省 青岛市

我们再以商品表做一个说明

编码 商品名称 价格 库存 制造工厂
1 iPhone 13 白色 1999 100 台湾富士康
2 iPhone 12 黑色 1299 20 北京富士康
3 iPhone 13 红色 2239 30 上海英华达

依旧是依照上述规则,首先我们找到已无法再次分割的属性

现在不可再分割的属性有 编码、价格(以只有RMB为准)、库存,而商品名称及制造工厂想必大家也知道,这是可以再分的属性吧,那么看下方符合第一范式的数据表设计

编码 品牌 型号 颜色 价格 库存 制造工厂(所在城市) 制造工厂名称
1 iPhone 13 白色 1999 100 台湾 富士康
2 iPhone 12 黑色 1299 20 北京 富士康
3 iPhone 13 红色 2239 30 上海 英华达

我们将商品名称与制造工厂进行以下的拆分,以达到不可再分的属性

其关系模式为:

商品名称(品牌,型号,颜色)
制造工厂(制造工厂所在城市,制造工厂名称)


看到这里,想必你已经搞懂第一范式的设计规则了,那么我们继续第二范式的学习。

2NF 第二范式

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第4张图片

遵循的规则:首先必须符合第一范式要求,其次一个表中只能保存一种数据,确保每一列都与主键相关,我们以课程编码为主键,除课程名称以外的其他信息与主键无关,所以我们只需要独立课程编码与课程名称,其他则新建一张表。

课程编码 课程名称 讲授老师 老师性别 老师联系方式
10001 C++程序设计 张三 1888888888
10002 数据结构 李四 1999999999
10003 操作系统 王五 1777777777

课程表

课程编码 课程名称
10001 C++程序设计
10002 数据结构
10003 操作系统

老师表

课程编码 讲授老师 老师性别 老师联系方式
10001 张三 1888888888
10002 李四 1999999999
10003 王五 1777777777

这样拆分后,我们就符合了第二范式的要求,并且也符合第一范式的要求,没有可再分的属性。


我们再以上述符合第一范式的商品表为例

编码 品牌 型号 颜色 价格 库存 制造工厂(所在城市) 制造工厂名称
1 iPhone 13 白色 1999 100 台湾 富士康
2 iPhone 12 黑色 1299 20 北京 富士康
3 iPhone 13 红色 2239 30 上海 英华达

这里以编码和品牌为联合主键,与主键无关的属性新建立一张表。

生产商表

编码 制造工厂(所在城市) 制造工厂名称
1 台湾 富士康
2 北京 富士康
3 上海 英华达

商品表

编码 品牌 型号 颜色 价格 库存 生产商编码
1 iPhone 13 白色 1999 100 1
2 iPhone 12 黑色 1299 20 2
3 iPhone 13 红色 2239 30 3

这样既符合了第二范式要求。

我们已经对第二范式有了一个大概得了解,不要停,第三范式在等你!

3NF 第三范式

遵循的规则:要先符合第二范式的要求,并且除主键列的其它列之间,不能有传递依赖关系。

这里先解释下,啥是传递依赖,以下列订单表为例 ,我们通过订单编码可以查到商品名称,但通过商铺编码也可以查找到发货仓及联系方式。既订单编码->发货仓,商铺编码->发货仓,这则产生传递依赖,通俗点讲究是如果除了主键(订单编码)外,不能再有有属性相关的非主键(商铺编码|发货仓),我们只能通过主键查到所有信息,达到独占的情况,意味着下条SQL语句不能让他有效,则就达到了第三范式的要求。

SELECT 发货仓,店铺电话 FROM 订单表 WHERE 商铺编码 = S1
订单编码 商品名称 商铺编码 发货仓 店铺电话
NS001 小米手机 S1 某东华北发货仓 1888888888
NS002 三星手机 S2 某猫华东发货仓 1999999999
NS003 华为手机 S3 某多华西发货仓 1777777777

根据下述拆分达到第三范式要求

订单表

订单编码 商品名称 商铺编码
NS001 小米手机 S1
NS002 三星手机 S2
NS003 华为手机 S3

商铺表

商铺编码 发货仓 店铺电话
S1 某东华北发货仓 1888888888
S2 某猫华东发货仓 1999999999
S3 某多华西发货仓 1777777777

刚刚讲到第三范式一定满足第二范式,而第一范式一定满足第一范式,那么我们看下刚刚拆好的订单表

  1. 无再可拆分的属性,符合第一范式。
  2. 无与主键无关属性,符合第二范式。
  3. 无传递依赖关系,符合第三范式。

所以说,当你符合第三范式时,你实际已经符合了第一第二范式,那么关系型数据库的三大范式我们就讲到这里,数据中可能有些歧义,请理解原理,勿细纠结,谢谢。

反范式设计的目的

当然范式只是提出的规范,但一些特殊情况下,我们要考虑的点比较多,例如

  1. 并发读。
  2. 减少表关联次数。
  3. 数据表的冗余设计。
  4. 热数据与冷数据。
  5. 数据的非实时性。

这里与三大范式做一个对比(个人见解)

  • 减少表关联次数 = 违反了第二范式
  • 数据表的冗余设计 = 违反了第三范式

当然也不是一概而论,这里以订单表为导向,来讲解一下为什么我们会迫不得已违反范式规则。


【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第5张图片
这里做出一个提问

用户下单后,商品的基本信息如果进行表关联的方式,既订单表的商品编码关联商品表的编码,会出现什么问题?

大概会出现这样一个问题:

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第6张图片

用户购买了一台HP打印机1999元后,商家对当前这个商品进行了修改,改为了一台华硕笔记本,那么通过表关联(设符合范式规则),用户会不会疯掉?

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第7张图片

那么如何解决这一问题?

这就使用了我上述提出的数据的冗余设计,将商品基本信息直接存入订单表中,这是根据常识而定的,就跟你去商场买了一个西瓜花了20元,次日这个西瓜无论涨价还是降价,商场不会要求你补足差价,你也无法要求商场返还差价(当然这与某东买贵包赔无关,不要较劲)。

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第8张图片

那么在互联网的时代,当你下单的那一时刻,你购买的商品信息则就已经固定,无论商家是修改商品,还是删掉商品,或者商家倒闭了关闭店铺。你购买的商品永远会在你的订单内看到,当然如果商品失效,你在点击进入后,某宝可能会给到你一个快照,这个快照依旧是在你下单时保存的数据。

你现在应该可以理解,为什么需要反范式,类似的例子还有很多,我在我的电商设计相关文章内有多次提出类似的需求,至此我就不一一例举了

当然在正常情况下,你依旧需要根据三大范式去设计你的业务,这是行业规范,只有规范统一,你才不会“坑”你的接班人。


那么反范式设计的优点有哪些呢?

  1. 提高查询速度。
  2. 避免多表查询。
  3. 降低数据库的压力。

反范式应该注意的问题

【一文秒懂】带你彻底搞懂范式与反范式数据库设计_第9张图片

  1. 过多冗余数据导致存储量过大。
  2. 必要时需配合内存数据库实行。
  3. 违反了范式规则,会出现插入异常、查询异常等。

致谢

感谢你看到这里,希望本篇可以帮助到你,谢谢。

你可能感兴趣的:(【一文秒懂】带你彻底搞懂范式与反范式数据库设计)