数据库的设计范式与疑惑
2016-04-27 10:58
204 查看
数据库的3大设计范式:
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)
和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
一.数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。
例如,如下的数据库表是符合第一范式的:
而这样的数据库表是不符合第一范式的:
二.数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖
部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况.第二范式(2NF)也即所有非关键字段都完全依赖于任意一组候选关键字。
假定选课关系表为SelectCourse(学号,姓名,年龄,课程名称,成绩,学分),关键字为组合关键字(学号,课程名称),因为存在如下决定关系:
引用
(学号,课程名称) → (姓名,年龄,成绩,学分)
这个数据库表不满足第二范式,因为存在如下决定关系:
引用
(课程名称) → (学分)
(学号) → (姓名,年龄)
即存在组合关键字中的字段决定非关键字的情况。
把选课关系表SelectCourse改为如下三个表:
引用
学生:Student(学号, 姓名, 年龄);
课程:Course(课程名称, 学分);
选课关系:SelectCourse(学号, 课程名称, 成绩)。
这样的数据库表是符合第二范式的,消除了数据冗余、更新异常、插入异常和删除异常。
另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。
三.在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。
所谓传递函数依赖,指的是 如果存在"A → B → C"的决定关系,则C传递函数依赖于A。
假定学生关系表为Student(学号,姓名,年龄,所在学院,学院地点,学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
引用
(学号) → (姓名,年龄,所在学院,学院地点,学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
引用
(学号) → (所在学院) → (学院地点,学院电话)
即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况。
把学生关系表分为如下两个表:
引用
学生:(学号,姓名,年龄,所在学院ID);
学院:(学员ID,学院名称,地点,电话)。
这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
数据库设计的一些疑惑:
1:数据库中的数据应该采用逻辑删除还是物理删除?
引用
最好不要物理删除,应该清楚,业务上所谓的删除和技术实现上的删除不是一个意思
2:数据库要记录数据的变更改怎么设计?
引用
要记录数据的变更记录,可以采用一个history表来记录历史变化。比如设计一个表叫做user,还有一个叫做user_history。那么每次user永远记录最新的记录,而user_history则记录每次变化之前的记录。
3:一年的数据量大概有700到1000万条记录的样子,所以在这里面操作起来很慢,然后系统的并发量也很大,平均下来,大概70个请求/s,原来的老系统不怎么稳定
引用
1.一年700-7000万条,70q/s,这个能算是数据量很大并发很大?一般数据库都能轻松处理吧。注意数据库配置、索引就可以了。
2.最简单的方法,就是利用数据库的表分区功能,这个功能Oracle,SqlServer2005都支持的。就利用表的时间字段来进行分区就可以了。这样按日期进行查询的时候速度比普通索引要快很多。
3.LZ的数据量其实并不算大,可以说如果对于oracle这样的数据库简直就是小菜。每天晚上可以定时做索引,定期做物理备份。
4.分区表就好了,没必要一个月一张表
5.分区表技术目前已经很成熟了。如果用的是oracle,目前,Sybase数据库也支持此项技术。所以几千万条记录并不会引起太大的瓶颈。
4:博客 活动 BBS 知识库文章 新闻 ...这些东西都有一个title 一个content
方案一 抽象到一起,建item表,以及item的分类以及评论,共3表,用item_type判断属于哪个种类,好处是可以少建很多模型,开发量少一点,缺点是性能差一点,灵活性差一点,还会有一些数据冗余。
方案二 传统的方式,有啥建啥,博客 活动 BBS 知识库文章 新闻,以及他们的分类和评论表,3*5=15个表。
引用
1:建item,然后其他的model继承item,因为这些model还有扩展的可能,so,必须分开,不能用item_type。。。
2:数据库建模和你的领域建模 , 还是有一定区别的
3:这种多态结合(polymorphic association)是不被推荐的,最大的问题是低效的索引。
4:项目小、数据量不大、一个人做,无所谓。如果多人分工、数据量有点大,第一种是不太好的。
5:关于数据库设计还需不需要的主外键的问题
要的理由就是,保持数据的完整性,而不要的理由就是可以提高数据库的性能。大多数认为要。也有认为不要的:表之间的关系在代码层关联。
引用
其实,对于主外键的建立也没有一个必然的规律,如果为了性能而言,不加是有一些提升,但是数据完整性则归到了程序中,写程序的时候就一定要对数据进行控制,特别是级联删除和更新,当然,orm的出现可以是我们在对象上再次构建一种这样的对象之间的关系,但是对于数据的完整性而言,见外键则是一种很好的约束,所以,还是针对应用采取不同的方式
数据库的设计范式是数据库设计所需要满足的规范,满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)
和更新(update)操作异常。反之则是乱七八糟,不仅给数据库的编程人员制造麻烦,而且面目可憎,可能存储了大量不需要的冗余信息。
一.数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。
例如,如下的数据库表是符合第一范式的:
而这样的数据库表是不符合第一范式的:
二.数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖
部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况.第二范式(2NF)也即所有非关键字段都完全依赖于任意一组候选关键字。
假定选课关系表为SelectCourse(学号,姓名,年龄,课程名称,成绩,学分),关键字为组合关键字(学号,课程名称),因为存在如下决定关系:
引用
(学号,课程名称) → (姓名,年龄,成绩,学分)
这个数据库表不满足第二范式,因为存在如下决定关系:
引用
(课程名称) → (学分)
(学号) → (姓名,年龄)
即存在组合关键字中的字段决定非关键字的情况。
把选课关系表SelectCourse改为如下三个表:
引用
学生:Student(学号, 姓名, 年龄);
课程:Course(课程名称, 学分);
选课关系:SelectCourse(学号, 课程名称, 成绩)。
这样的数据库表是符合第二范式的,消除了数据冗余、更新异常、插入异常和删除异常。
另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。
三.在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。
所谓传递函数依赖,指的是 如果存在"A → B → C"的决定关系,则C传递函数依赖于A。
假定学生关系表为Student(学号,姓名,年龄,所在学院,学院地点,学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
引用
(学号) → (姓名,年龄,所在学院,学院地点,学院电话)
这个数据库是符合2NF的,但是不符合3NF,因为存在如下决定关系:
引用
(学号) → (所在学院) → (学院地点,学院电话)
即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况。
把学生关系表分为如下两个表:
引用
学生:(学号,姓名,年龄,所在学院ID);
学院:(学员ID,学院名称,地点,电话)。
这样的数据库表是符合第三范式的,消除了数据冗余、更新异常、插入异常和删除异常。
数据库设计的一些疑惑:
1:数据库中的数据应该采用逻辑删除还是物理删除?
引用
最好不要物理删除,应该清楚,业务上所谓的删除和技术实现上的删除不是一个意思
2:数据库要记录数据的变更改怎么设计?
引用
要记录数据的变更记录,可以采用一个history表来记录历史变化。比如设计一个表叫做user,还有一个叫做user_history。那么每次user永远记录最新的记录,而user_history则记录每次变化之前的记录。
3:一年的数据量大概有700到1000万条记录的样子,所以在这里面操作起来很慢,然后系统的并发量也很大,平均下来,大概70个请求/s,原来的老系统不怎么稳定
引用
1.一年700-7000万条,70q/s,这个能算是数据量很大并发很大?一般数据库都能轻松处理吧。注意数据库配置、索引就可以了。
2.最简单的方法,就是利用数据库的表分区功能,这个功能Oracle,SqlServer2005都支持的。就利用表的时间字段来进行分区就可以了。这样按日期进行查询的时候速度比普通索引要快很多。
3.LZ的数据量其实并不算大,可以说如果对于oracle这样的数据库简直就是小菜。每天晚上可以定时做索引,定期做物理备份。
4.分区表就好了,没必要一个月一张表
5.分区表技术目前已经很成熟了。如果用的是oracle,目前,Sybase数据库也支持此项技术。所以几千万条记录并不会引起太大的瓶颈。
4:博客 活动 BBS 知识库文章 新闻 ...这些东西都有一个title 一个content
方案一 抽象到一起,建item表,以及item的分类以及评论,共3表,用item_type判断属于哪个种类,好处是可以少建很多模型,开发量少一点,缺点是性能差一点,灵活性差一点,还会有一些数据冗余。
方案二 传统的方式,有啥建啥,博客 活动 BBS 知识库文章 新闻,以及他们的分类和评论表,3*5=15个表。
引用
1:建item,然后其他的model继承item,因为这些model还有扩展的可能,so,必须分开,不能用item_type。。。
2:数据库建模和你的领域建模 , 还是有一定区别的
3:这种多态结合(polymorphic association)是不被推荐的,最大的问题是低效的索引。
4:项目小、数据量不大、一个人做,无所谓。如果多人分工、数据量有点大,第一种是不太好的。
5:关于数据库设计还需不需要的主外键的问题
要的理由就是,保持数据的完整性,而不要的理由就是可以提高数据库的性能。大多数认为要。也有认为不要的:表之间的关系在代码层关联。
引用
其实,对于主外键的建立也没有一个必然的规律,如果为了性能而言,不加是有一些提升,但是数据完整性则归到了程序中,写程序的时候就一定要对数据进行控制,特别是级联删除和更新,当然,orm的出现可以是我们在对象上再次构建一种这样的对象之间的关系,但是对于数据的完整性而言,见外键则是一种很好的约束,所以,还是针对应用采取不同的方式
相关文章推荐
- redis数据类型(字符串)
- SQL监测语句
- oracle 中 in函数
- mysql主从库配置ps:mysql5.6
- Orcle设置编码
- mongodb aggregation在mongoengine的实现
- 织梦标签dede:sql根据页面动态参数变量动态查询调用其它信息
- 解决oracle使用rownum排序分页排序字段不唯一导致分页错误
- Oracle创建用户、表空间并设置权限
- ActiveMQ将消息持久化到数据库
- wordpress 如何从后台数据库修改theme(图文教程)
- libevent/libev/libuv/redisev比较
- Mysql错误: Lock wait timeout exceeded解决办法
- Mysql学习笔记(三)
- Lepus(天兔)数据库监控系统
- Oracle 自定义函数
- mysql时间相关的函数
- sqlite3使用简介
- Mysql存储过程关于游标的解决方案
- MySQL数据库优化