对于懂得软件工程的人来说,标题就是一句废话,没有需求分析,哪来的设计?软件设计和实现中,开发者往往会在不知不觉中忽略用户的需求,站在开发者的角度,按照自己的意愿去设计软件。同样在为系统设计数据库的时候,也存在类似的现象,也许你设计的数据库满足三范式的原则,而且非常灵活,但是用户方的负责人一看就知道这种严格按照理论设计的数据库是不能用的,会给带来好多问题,尤其是性能方面的。
那么应该怎样去考虑数据库的设计呢?个人理解的是,应该以理论知识为基础,以需求为导向进行数据库的设计,不能只是将系统的实体抽象出来,然后按照三范式的理论进行设计,而完全不考虑系统在实际使用中面临的问题,换句话说就是站在使用者的角度去看待数据库的设计。最近在设计机房收费系统的数据库,比较迷茫,所以就广泛的阅读博客,好多人都有自己的理解,在看到高玮师哥的实习感悟,顿时有点感觉了。
机房收费系统的数据库如何设计暂时不谈,先来看一个例子:最近学校正在搞“校园一卡通”的项目,期望将学生使用的饭卡和银行卡绑定,为学生充值提供便利,这样你就不用去ATM机排半天队,取出现金,完了再跑到食堂排半天队才能充上钱,直接用手机银行和网上银行就能搞定。在办理一卡通之前,需要核对个人信息,我核对的时候将屏幕的信息用手机拍了下来,方便以后查阅,我们就以一卡通的信息为例,谈谈数据库的设计。
一卡通的信息主要有这么几项:卡号、姓名、学号、性别、民族、余额、国籍、手机号、部门(专业班级等)、身份证号、银行卡号,如果让你为这个系统设计数据,你会怎么考虑?
以我个人的理解,可以抽象出这么几个实体:学生、饭卡、身份证和银行卡,然后我们将上述信息按照第一范式的原则给他们归类:
学生:学号、姓名、部门、手机号
饭卡:卡号、姓名、余额
身份证:身份证号、姓名、性别、民族、国籍
银行卡:卡号、姓名、余额
这是对一卡通屏幕显示的信息的一个分析,去稍微还原一下数据库的结构,可能只是部分的信息,但是不影响我们说明问题,一卡通的后台数据库我也接触不到,所以只能这么琢磨了。
在核对信息的时候,我们只需将饭卡贴在自助终端的射频区域即可显示全部信息,因此饭卡号是一个主键,我的个人信息缺了手机号,在添加的时候只需提供身份证即可,将我的个人信息全部找出,说明身份证号也是一个主键。
如果以上面的数据库表的结构,如何通过我的身份证号查找和修改我的手机号呢?你也许会想到使用数据库的联合查询,即join关键字,让学生表的姓名等于身份证的姓名,即可查出我的手机号。但是重名问题怎么解决?多个人的姓名一模一样,怎么精确定位?
两种办法,一种是在身份证的表中添加学号的字段,因为学号是唯一的;另一种是将学生表和身份证表合并,身份证号作为学生信息的一部分,合并两个表中的的“同类项”(即重复信息)。那种办法好呢,更贴近需求呢?
我个人觉得第二种号,两点原因,第一,身份证的信息里添加一个学号,总觉得别扭,不符合自然认知;第二,合并表之后,就不需要联合查询,在海量数据查询中的效率会快很多,身份证号作为学生信息的一部分,比较合适,况且可以消灭数据冗余。
现在你想想为什么我们之前用的机房收费系统的学生信息会和卡的信息在一张表中了吧,也许有他们自己的道理,总之在设计数据库的时候,应该让需求来引导设计,不要只是单纯的去考虑什么范式和原则等这些理论知识,应该以实际应用为出发点。在实际工作中,数据库的设计目标不是最正确,而是最优化。
需求引导设计 切莫教条主义