以下内容参考:http://blog.csdn.net/elemman/article/details/50966164#inf
第一范式(1NF)
- 概念
数据表的每个字段(属性)必须是唯一的、不可分割的。
- 唯一性
比如说:在一张学生信息表里不能有两个名称都是name的字段。
- 不可分割性
比如说:在一张学生信息表不能出现类似name_mobile这样的字段,很明显name_mobile是可以分割成name和mobile两个字段的。
第二范式(2NF)
- 概念
数据表的每条记录必须是唯一的(主键约束),且非主属性依赖于主属性。
- 唯一性
比如说:不能同时存在id = 1的记录(id为主键)。
- 依赖性
比如说:在一张学生信息表(id为主键),不应该出现course_name(课程名称,依赖于course_id)这样的字段,因为,如果有一天,《心理健康教育》课程名要改成《心理健康教育杂谈》,这就得需要改课程表,还得回来修改学生信息表的课程名称。
第三范式(3NF)
- 概念
数据表中不应该存在多余的字段,也就是说每个字段都不能由其他字段推理得到。
- 例子
比如说:学生信息表里不能同时存在province_id(省份ID)、city_id(城市ID)这两个字段,因为province_id可以由city_id推理得到
字段冗余
- 是什么
数据表中存在多余的字段。
例如:订单表:订单信息,商品id,商品名称。这里的商品名称是冗余的,在商品表中有这个字段,根据商品id可以关联到。
毫无疑问,字段冗余是违反第三范式的。
- 为什么
1.考虑性能:以时间换空间
在数据库的实践过程中,我们可能遇到数据量非常大的数据表,这时候去做join查询是非常损耗性能的,甚至导致数据库连接超时、挂掉等问题。所以呢,有时候就需要数据库多冗余设计,对一些字段做冗余到关联表中,以避免大表之间的join。
弊端:难以维护。更新表数据时需要同时更新多个表。
比如,order:orderid,userid,username;user:userid,username。当用户更改username时,所有有username的表都需要update。
2.考虑业务:快照场景
交易场景大部分是数据快照。用户下单时候的用户名、地址、商品名称、商品描述等,若采用关联,商品在下单后发生了更新的话再去关联查询就会导致和用户操作时的数据不一致,从而产生纠纷。
比如,order:orderid,goodsid;goods:goodsid,price。用户今天下单,价格为100。过了几天卖家涨价了,价格涨为200。用户申请退款,系统给他退款200。这显然不合理。所以这里price需要冗余,order:orderid,goodsid,price;goods:goodsid,price。
其实严格来讲,这也可以说不是冗余,因为两个表中的price含义有所区别。order表中的price表示“下订单时的商品价格”,goods表中的price表示“商品现在的价格”。