面试被问到过,当时说实话,是真忘记了,虽然平时设计表都很顺,但用理论表达出来,有时候却欲言又止
今天我把三范式记录下来,分享给大家,这是我面试遇到过的问题
数据库有规范,设计有规则,所以要满足标准,对于PHP开发,熟悉三大范式就行了
第一范式:1NF 原子性
什么是原子性?通俗的讲,就是代表某个特性细得不能再细了,具体的指明表示它,并且它不能再进行分割
例子:
有张user表,它有以下三个字段:
id user_name age sex
那么这样的设计是合理的,因为你的姓名不可能再分吧,你的年龄是一定的吧,性别就更不用说了
那举个反例,比如记录一个人点了什么餐,有菜名吧,如果你把字段值设置为:菜,合理吗?显示,谁知道是什么菜?
所以这里应该有张食谱的表,记录每一个菜的菜名,这就是原子性
第二范式:2NF 唯一性
定义:保证每一行的数据是唯一
怎么表示呢?通常是用primary key 主键来实现的
你会发现在工作中每张表几乎都有这个primary key 并且很有可能是auto_increment
当你的表行数据是唯一的,就满足了二范式
第三范式:3NF 数据冗余
定义:当数据表中有字段是可以被推导出来的情况,这时候不能有冗余数据
什么意思呢?
比如有下面字段的表
id,name,age,sex,class_id,classname,depart
另一张表
id,classname,depart
这时候,前面一张表是可以通过class_id来推导出后面一张表的数据,那classname,depart就是冗余数据了
在开发中,通俗的讲,当分开表的时候可以通过外键来关联表
有时候没有冗余数据并不一定是合理(反三范式)
适当的数据冗余是有助于开发的,也是提升效率的一种方法
这种需要适当加冗余字段的情况,一定要根据业务场景来设计字段
例子:QQ空间的相册
每个相册都有点击数,相册里的每张图片也有点击数,这时候设计表来完成这样的业务场景就需要用到冗余字段,看下表
相册表:
id , abname, view_times
图片表:
id, abname_id, img_path, view_times
相册表明显有个冗余字段view_times,那为什么要这样做呢?
假设如果没有冗余的情况下,你肯定会这么干:
通过一对多的关联关系,通过相册表的id到图片表中去找到与id相等的abname_id
然后把所有找到的图片表中的数据的view_times通过聚集函数sum求和来显示对应相册的点击数
这种情况是不是每次渲染相册的时候都得先关联查询一下,然后在求和,最后再返回数据?
这时候设计一个冗余的view_times字段,只需要查一次就得到了数据,哪个合理?
显然直接查相册表的view_times来渲染比没有冗余字段要快得多,而且更合理
那怎么来计算相册表的view_times的值呢?下面给出逻辑:
当前相册下的图片被点击是不是会记录到图片表的view_times中?
这时候同步更新一下相册表的view_times数据就行了