数据库设计经验,可参考:
https://www.cnblogs.com/imgogogo/archive/2007/12/06/2124665.html
数据库三范式(3nf标准),可参考:
https://m.wenda.so.com/q/1356146443069601?ivk_sa=1024320u
数据库设计五大约束,可参考:
https://www.cnblogs.com/zhouguowei/p/9268788.html
本篇博客主要基于以下几个方面对本次的数据库设计进行评价:
1. 考虑α版本项目需求评价数据库实体设计完整性
2. 基于数据库设计经验对数据库进行修改与优化
3. 基于三范式(3nf)与五大约束对数据库进行理论验证
4. 数据库设计项目总结
一. 考虑α版本项目需求评价数据库实体设计完整性
我们通过我们α版本的迭代计划,进行需求文档部分需求的迭代开发。在开发前,我们基于模块的数据需求,具体化数据结构作为实体,根据实体间的相关关系与内容,通过powerdesigner,进行概念模型CDM和物理模型PDM的初步设计,以下是相关步骤:
1. 通过功能模块进行实体的设计
我们每进行一个模块或功能(不严谨的说法)的设计开发,必然要涉及到数据的增删查改,这也是我们需要设计数据库的目的,对于每一个功能,我们选取其需要的数据 以及关联数据设计实体,以注册,登录为例,我们首先在注册成功后会将用户名、密码、用户电话存入数据库,在登录时会在数据库中查找该用户的用户名与密码,并在云端服务器与用户上传的账户与密码进行比对,很明显的,我们就会想到我们需要一个用户实体去存储这些内容,再结合我们有着不同权限的用户,一些信息的记录,我们依次此设计了这样的实体,这里的最后三个属性为大型数据库的基本属性,用于记录变更追源等操作。
2. 进行用例关系的描述
数据库实体间主要有三种关系:一对一,一对多,多对多,其中,多对多的关系需要加入中间表来保证正确(多对多关系在本数据库设计中未出现)
一对一实例:一个班级有多个学生。
一对多实例:一个班级有多个学生。(较为常见)
多对多实例:多对多就是双向一对多,一个学生可以选择多门课,一门课也有多名学生。
我们基于我们数据库实体的关系进行确立每个实体间的关系并通过RE图进行表示,因为只简单画了草稿,所以下面以学生RE图为示例:
3. 根据前面设计的实体与关系,对照RE图设计初步的数据库。
实际结果与RE图相似,以用户实体和反馈实体及用户记录实体为例。
在这一部分的实体关系中,我们根据向老师的询问,我们不采取通过个人部分信息作为主键,如username等,而是对所有的表设置id作为主键,同时我们可以看到,user实体与其他两个实体间的关系都是一对多,一个用户有多条记录,有多条反馈。且我们可以通过username作为关联多个实体的外键进行实体间的操作。对于每一个实体来说,我们根据我们的需求设定了相关的属性,并对其类型做出了确定,以及一些特性的添加,如自动增长。
二. 基于数据库设计经验对数据库进行修改与优化
我们在网上找到了一个非常流行的数据库的设计经验的博客,也从中学到了十分多的内容,对我们数据库的设计起到了非常大的帮助,在这里,我们举几个比较经典的例子,来说明一些较好的数据库设计方法与技巧。
1)每个表中都应该添加的 3 个有用的字段
* dRecordCreationDate,在 VB 下默认是 Now(),而在 SQL Server 下默认为 GETDATE()
* sRecordCreator,在 SQL Server 下默认为NOTNULL DEFAULT USER
* nRecordVersion,记录的版本标记;有助于准确说明记录中出现 null 数据或者丢失数据的原因
仔细考虑就会发现,这三个字段确实十分的重要,无论是查找修改的日期,对混乱的变更进行管理,亦或者查询日期等等,这三个字段都可以提供有用的帮助,且经过我们在网上的查找,这三个字段基本运用在很多大型数据库的开发中,所以我们在我们基本所有的表上也创立了以上的实体属性。
2)保存常用信息
让一个表专门存放一般数据库信息非常有用。我们应该在这个表里存放数据库当前版本、最近检查/修复(对 FoxPro)、关联设计文档的名称、客户等信息。这样可以实现 一种简单机制跟踪数据库,文章中提到,当客户抱怨他们的数据库没有达到希望的要求而与你联系时,这样做对非客户机/服务器环境特别有用。所以我们在我们的数据库设计中也专门建立了这样一张悬浮表独立存储,以下为展示:
3) 别忘了外键
大多数数据库索引自动创建的主键字段。但我们不应该忘了索引外键字段,它们在我们想查询主表中的记录及其关联记录时每次都会用到。还有,我们应该不要索引memo/notes 字段而且不要索引大型文本字段(在我们数据库中有基于爬虫爬取的text字段),文中提到这样做会让索引占据大量的数据库空间。我们缺少了对外键的格外考虑,但这个经验提醒了我们相关方面的检查。
4) 不要用用户的键
我们其实在最开始的时候就犯了这样的错误,我们在很多表中直接用username作为主键,但其实这个键是用户可操作的,在看到这部分的经验贴时,我们才明白了这个错误的严重性,文中说道,在确定采用什么字段作为表的键的时候,我们一定要小心用户将要编辑的字段。通常的情况下不要选择用户可编辑的字段作为键。这样做会迫使你采取以下两个措施:
* 在创建记录之后对用户编辑字段的行为施加限制。假如你这么做了,你可能会发现你的应用程序在商务需求突然发生变化,而用户需要编辑那些不可编辑的字段时缺乏足够的灵活性。当用户在输入数据之后直到保存记录才发现系统出了问题他们该怎么想?删除重建?假如记录不可重建是否让用户走开?
* 提出一些检测和纠正键冲突的方法。通常,费点精力也就搞定了,但是从性能上来看这样做的代价就比较大了。还有,键的纠正可能会迫使你突破你的数据和商业/用户界面层之间的隔离。
所以还是重提一句老话:你的设计要适应用户而不是让用户来适应你的设计。
不让主键具有可更新性的原因是在关系模式下,主键实现了不同表之间的关联。比如,Customer 表有一个主键 CustomerID,而客户的定单则存放在另一个表里。Order 表的主键可能是 OrderNo 或者 OrderNo、CustomerID 和日期的组合。不管你选择哪种键设置,你都需要在 Order 表中存放 CustomerID 来保证你可以给下定单的用户找到其定单记录。
假如你在 Customer 表里修改了 CustomerID,那么你必须找出 Order 表中的所有相关记录对其进行修改。否则,有些定单就会不属于任何客户——数据库的完整性就算完蛋了。
如果索引完整性规则施加到表一级,那么在不编写大量代码和附加删除记录的情况下几乎不可能改变某一条记录的键和数据库内所有关联的记录。而这一过程往往错误丛生所以应该尽量避免。
我们完整的引述了这段内容,想提醒我们自己也告诉大家,千千万万不要出现这样容易犯且致命的错误。
三. 基于三范式(3nf)与五大约束对数据库进行理论验证
虽然五大约束我们已经通过专业课程了解了,但三范式其实在数据库课程中还没有学习到,但如果自我学习的话又会花费我们开发的时间,我们十分的纠结,但最终经过商 议与决策,我们还是决定努力学好这部分内容并依次来规范我们的数据库的设计。既然要做一件事,就做到最好!最终,通过学习与对我们数据库设计的检验后,我们发现, 虽然因为学过有关五大约束的内容,比如必须设计主键,设计外键约束等,我们做的已经比较好了,且我们相信大多数同学也会跟我们一样做的很好,但是对于三大范式的遵 循,我们做的比预想中的要差很多,出现了不少来自于第二范式、第三范式的问题,也就是部分依赖和传递依赖的设计,以下将举例说明。
1.第二范式相关问题
第二范式求表中的所有列,都必须依赖于主键,而不能有任何一列与主键没有关系,也就是说一个表只描述一件事情;
这样说比较抽象,举个例子就是如订单表,它只描述订单相关的信息,所以所有字段都必须与订单id相关产品表只描述产品相关的信息,所以所有字段都必须与产品id相关;因此不能在一张表中同时出现订单信息与产品信息;如下图所示:
首先我们依此来检查我们设计的数据库,发现有很多表的内容其实是部分依赖的,具体体现在两个方面
1)部分属性不全依赖键
简单来说就是表的内容多了,或者放错了表,在我们的数据库系统最开始的设计中,将电话放到了用户信息表中,其实因为在注册的时候就需要电话来发送验证 码,所以这个放到用户表中更加合适。
2)键设置不全导致部分依赖
这个很容易理解,就是主键可能由多个属性构成,如果我们没考虑全,也会不满足第二范式,所以设置唯一id也可以很好地避免这个问题。以下是基于我们数据库的举例。
这里一个博客的主键由博客id与username组成,但在一开始只考虑了id,所以导致了部分依赖。
2.第三范式的相关问题
必须先满足第二范式(2NF),要求:表中的每一列只与主键直接相关而不是间接相关,(表中的每一列只能依赖于主键);例如:订单表中需要有客户相关信息,在分离出客户表之后,订单表中只需要有一个用户id即可,而不能有其他的客户信息。因为其他的客户信息直接关联于用户id,而不是直接与订单id直接相关,如下图所示:
在我们的数据库中,也出现了这种很容易犯的错误,我们设置了三个属性为,登入时间,登出时间和使用时长,但我们可以很明显的发现,使用时长可以跟据登出时间减去登入时间得到,这就是一个典型的间接相关的例子。当然,在询问老师后得知,第三范式不一定在任何情况都需要满足,我们可能还需要考虑这种间接关系计算的复杂性,如果为了系统性能考虑,那么在有些情况下我们是不一定需要满足第三范式的。
数据库设计最终结果:
四. 数据库设计项目总结
这次的数据库设计项目,我认为是在整个开发中相当重要的一部分。
首先,我们通过网上对于数据库设计的经验,借鉴数据库建立的新奥尔良方法,结合在数据库课程中学到的相关设计流程,最终完成了
本次的设计,并且也有了一定的数据库设计经验。其次,在这次的数据库设计任务中,我学到了powerdesigner的使用方法,明白了数据
库的3nf范式与五大约束的规范,了解了数据库建立的很多经验并进行了实践,这种从0到1的设计经验,将会带我在以后的项目数据库设
计中更加游刃有余,更加得心应手,这种做中学的方式也让我更加深刻的领会到了软件工程导论教授的知识在实践中的运用以及一些自己
似懂非懂的概念与数据库设计在实操的情况下如何去完成,真的极大地提升了我的数据库设计能力与学习兴趣。
更多的,在这次数据库设计实践中,虽然出现了很多的问题,也造成了我们效率不高,错误频出的结果,但当最终完成了这次的任务,
我们得到了非常多的团队数据库设计开发的经验。在之后的项目开发过程中中,我们运用在这次开发中设计的数据库进行数据的处理,那
无疑可以让我们更加的上手与高效。我觉得项目流程的设置非常的合理,内容难度也衔接有序。 最后,我想说的是,通过这次的开发,我
明白了其实很多的困难并不来自于实践有多困难,而是在于与队员的协作、沟通团结,主体设计的宏观结构的设计与思路,开发方法的选
择等等问题上。尤其是如何学会与团队的其他人相处与合作,真的是非常重要的一件事,这是我在这次的数据库设计中学到的非常重要的
事,我相信,这也会在我以后的学习与工作中,起到非常大的帮助与作用!
最后,在本次项目的实现过程中,我出现了很多问题,请教了很多人,主要为同学和教授数据库实验课的老师,我发现这些老师非常的
和蔼可亲也乐于给我们解答问题,而且这种请教的效率要比我自己冥思苦想很久要来的高效很多,而我也会去给一些别的同学去解答问题,
这无疑极大地提高了我的团结协作的能力,也充分的培养了我的团队精神。当然,我也有时会选择去自己在一些平台上查询相关的资料与
解决方案。这也很好地提高了我的自我学习能力与资料查找能力。跟之前的项目一样的,只能说这次项目真的从多方面和多维度提升了我
个人的全面素质,真的是一次非常不错的项目经历。
希望接下来的项目迭代开发计划,我们也能游刃有余,顺利进行!