数据库设计杂谈

注:本人开发经验尚浅,下文主要谈的是自己的一些想法,不足之处请指出。

最近半年时间都花在管理系统的开放上面,对数据库的设计有一些自己的想法,在我看来数据库设计的key point就是妥协。一个设计的比较好的数据库都是在业务逻辑、设计规约和便于开发这三者之前来回考量,从而获得3-win的结果。下面主要是在思考和总结的点。

如何设计出高灵活性的数据库

可以说在项目交付前,需求不断在变,如何在需求改变的同时尽可能减少对表结构的修改是我现在考虑的问题。对于一般情况而言,在设计的时候我们可以适当添加一些预留的字段,需求改变的时候可以用上,或者说是添加不足的字段。但是也会出现一些比较麻烦的情况——旧表不足以进行修改维护,需要局部重新设计,这就会给开发带来比较多的麻烦,因为大多现在我们都会使用ORM。

eg1:
在贷款的业务流程中,每一笔借款申请需要进行审核。
起初,参与的审核角色只有2名,所以我选择了,直接添加字段到贷款申请表中。
之后,参与审核的角色数变多,并且审核产生的业务参数变多(例如各类附件、意见等),直接添加字段到贷款表中显得不那么合理,同时不利于审核流程的体现。因此,这一部分需要单独重新设计,根据业务流的需要,将审核的事件单独拉出来一张表,通过外键关联到申请表中。(流程复复杂可参考工作流引擎的设计思路)

这个案例里,最初的设计,觉得既然审核人数少,直接把审核信息添加到申请表中即可,不需要单独建表,也方便了开发,但是后来的需求改变就有单措手不及了。这里就感觉很矛盾,同时也发现数据库的设计居然也和软件工程那一套理论惊人的相似。在软件工程里面,我们经常会听到一句话“低耦合、高内聚”,一般是提醒我们,尽可能保证模块与模块之间相互独立,减少不必要的依赖关系。

这也就是困扰这我的地方,如果一开始设计就考虑单一职责,分成两张表,未免显得有些复杂化了,也不利于开发(需要维护1-n的关系)。毕竟代码一定程度上是可以重构的。

数据库原理在实际设计中的运用

我们在《数据库原理与设计》中学过很多的概念,由于实验环境的限制(数据量小、课设的业务偏简单etc.),导致很多概念在那时真的就变成了一个死记硬背的概念。这点或许随着开发经验的增长会豁然开朗吧。下面介绍几个,替他们刷一下存在感,内容都很浅,但也希望对在学习数据库的有一点帮助吧。

范式(NF)

1NF的定义为:符合1NF的关系中的每个属性都不可再分
2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖。
3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖。
...

范式的概念大家肯定背的很熟,本人研究生面试也考了这个。这一点其实大家在按设计数据库的时候都已经用上了。明确实体间的关系,画E-R图,其实就是对范式的运用。

索引(Index)

Index,面试的时候也经常会问到,但是呢学他的时候基本上感觉不到他的存在,毕竟测试的数据集太小了。底层的原理牵扯到数据结构,这里就不展开了。但是需要知道的是:

  • 需要做表连接的字段,需要添加index。
  • 经常需要查询的字段,需要添加index。
  • 很多字段需要联查的时候,需要添加组合查询。

下面是一个实际项目中的例子,可以感受下:
有一个地方需要数据展示,需要多表联查。下面就是建索引和不建索引的区别了。

事务(Transaction)

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。

这个写过管理系统的应该都明白。大概就是下面这个模型。JDBC中就有,在ssh或ssm中可以配合注解或配置文件来实现。

BeginTransaction{
    // to-do
    commit
}catch{
    rollback
}

一般在多表操作时必须使用事务!例如级联删除,多表修改。如果不使用,一旦出现异常,会导致数据不一致!

具体可参考:

锁(lock)

锁根据不同的法,可以分为乐观锁、悲观锁。也可以分为共享锁和排它锁。

一般在出现并发问题的时候会用到锁,具体可以看我另外一篇博客——并发初体验,解决小规模并发下单问题。里面详细讲了锁的描述和实现。

笔者经验有限,其实还有很多概念类似,数据库安全,容灾备份等没有接触到的,希望以后有机会可以补全。

冗余字段的利用

冗余字段的利用,其实仅仅是为了开发方便的一个tip。

具体可以看上面一个小例子。一笔借款需要经过很多人的审核才能通过。因此存在借款表审核流程表,两者一对多。通过借款单号可以去审核表中查询其所有的审核情况。

那么此时,我选择在借款表中存审核流程表id(外键)的同时,存下当前这一笔借款的审核信息。这么做的好处就是,我不需要去做表连接,直接可以查询到借款的当前进行到哪一流程,或者说申请失败,失败在哪一流程。从开发的角度,如果有一个页面需要显示出借款的当前流程,那就可以轻松查询到了。

毕竟,处理表连接操作是相对麻烦的,同时效率并不高。因此在存储条件允许的情况下,可以通过适当冗余来减少开发中的麻烦。这里就体现了数据库设计的一种妥协,现在存在冗余是违反了2-NF的,所以有的时候就需要凭经验来进行调整。对于不是频繁需要修改的字段,是可以适当冗余存取的,反之,经常需要修改的字段,如果冗余存取,一不小心很容易造成数据的不一致,就不建议了。

视图与冗余表

在谈冗余表前,先来看几个在Java OO中的概念,抛砖引玉一下。

VO(View Object):视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。
DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负载,但在这里,我泛指用于展示层与服务层之间的数据传输对象。
DO(Domain Object):领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。
PO(Persistent Object):持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应PO的一个(或若干个)属性。

首先,这些对象其实是和数据库中数据表存在一些关系的。我想说的是,在数据展示或数据传输时,可能会涉及多张表,这个时候我们会做的就是创建一个新的Object,然后讲多张表对应的持久化对象放进去,或者直接从多个表的持久化对象中抽取需要的字段。这个对象也就是上面提到的VO和DTO了。

这种做法同时也可以在数据库进行实现,那就是冗余表。其实也就是把很多张表的数据统一到一张表中去,为的也是查询和更新的方便。

之前遇到以下这个业务:

存在订单、订单明细之前一对多,订单又需要和卡绑定,一对多。现在我需要将数据一起显示出来看,同时粒度要最细,以订单明细和卡号的形式显示出来,t同时可更新。
eg:有订单记录A ,订单明细B1、B2,绑定了两张卡C1、C2,那么显示效果如下

C1 A B1
C1 A B2
C2 A B1
C2 A B2

这个时候考虑到如果创建一个DTO来保存这些数据的话,在查询组装上需要花很多的时间,于是就直接创建了一张冗余表,用于维护这层关系。那么通过这层冗余表查询出来的结果就是可以直接用于显示的,更新的时候也只需要直接找到外键进行更新就可以了。

我觉得使用DTO还是冗余表,完全就是取决于开发上的的便利以及是否需要对数据进行持久化了。

同样的,之前的例子提到是需要对数据进行更新或删除的,如果仅仅是为了数据的展示,例如一些统计数据的展示。那么就不需要冗余表了。数据库里面有个专有的概念——视图。比如说查询每天每年每季度的销售情况等等,直接用sql创建视图,查询以天为单位的结果,展示的时候直接从view中取数据即可,将复杂的sql语句就留在数据库那边了。

当然创建视图若使用大量表连接时,记得创建index进行优化,否则查询效率会很低。

数据字典与代码表

数据字典与代码表其实存储的就是一些常量了。

数据字典一般两张表,一张存类别,一张存键值对。数据字典一般用于存取一些不太会变的数据,例如性别、订单状态etc。而且这些数据量比较小,可以统一存储。

代码表,一般都是各管各存储的。例如文章分类表、标签表、省市区代码、商品分类etc。这些本来数据就大,并且有一定的业务性,有些会随着业务的扩大而变动,因此单独存表会比较好。

总结

一下子码了很多字,主要写了一些数据库中的一些概念在实际应用上的体现。表达了最近一段时间对数据库设计上面的一些思考和见解。人是会思想的芦苇,实践是检验真理的唯一标准,嗯……

原文地址:https://www.cnblogs.com/Sinte-Beuve/p/8598057.html

时间: 2024-10-10 03:06:22

数据库设计杂谈的相关文章

Java精品高级课,架构课,java8新特性,P2P金融项目,程序设计,功能设计,数据库设计,第三方支付,web安全,视频教程

36套精品Java架构师,高并发,高性能,高可用,分布式,集群,电商,缓存,性能调优,设计模式,项目实战,P2P金融项目,大型分布式电商实战视频教程 视频课程包含: 高级Java架构师包含:Spring boot.Spring  cloud.Dubbo.Elasticsearch,Redis.ActiveMQ.Nginx.Mycat.Spring.MongoDB.ZeroMQ.Git.Nosql.Jvm.Mecached.Netty.Nio.Mina.java8新特性,P2P金融项目,程序设计,

数据库设计时不得不违背三范式的情景

1.在进销存系统中,订单信息中关联到好多其他的基本信息,比如:客户,付款方式,货运方式等,这些信息是有专门表进行维护的,在下订单时也是用下拉框选择的,但在保存订单信息时,不能只记录所谓的外键ID,而是应该同时记录名称等其他的信息. 这是因为订单不能因为没有了客户ID或是付款方式ID而不知道客户与付款方式了.对于订单这种客观存在的事物,是具有一定的历史性质的,因此在设计时应该与其他的关联信息可以“断开”,这也就是保证了订单的独立性. 摘自:http://www.cnblogs.com/tongtk

从零开始编写自己的C#框架(9)——数据库设计与创建

对于千万级与百万级数据库设计是有所区别的,由于本项目是基于中小型软件开发框架来设计,记录量相对会比较少,所以数据库设计时考虑的角度是:与开发相结合:空间换性能:空间换开发效率:减少null异常......当然不同的公司与项目要求不同,初学者要学会适应不同的项目开发要求,使用本框架开发时,必须严格按照本章节的要求来设计数据库,不然可能会产生不可控的异常. 从零开始编写自己的C#框架 数据库设计规范   文件状态: [√] 草稿 [  ] 正式发布 [  ] 正在修改 文件标识: C#框架 当前版本

数据库设计的三大范式

数据库设计的三大范式 为了建立冗余较小.结构合理的数据库,设计数据库时必须遵循一定的规则.在关系型数据库中这种规则就称为范式.范式是符合某一种设计要求的总结.要想设计一个结构合理的关系型数据库,必须满足一定的范式. 在实际开发中最为常见的设计范式有三个: 1.第一范式 第一范式是最基本的范式.如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式. 第一范式的合理遵循需要根据系统的实际需求来定.比如某些数据库系统中需要用到"地址"这个属性,本来直接将"

MySql三大范式与数据库设计和表创建常用语句

[数据库设计的三大范式] 1.第一范式(1NF First Normal Fromate):数据表中的每一列(字段),必须是不可拆分的最小单元.也就是确保每一列的原子性. 例如: userInfo: '山东省烟台市 13181621008' => userAds:'山东省烟台市' tel:'13181621008' 2.第二范式(2NF):满足1NF后,要求:表中所有的列,都必须功能依赖于主键,而不能有任何一列与主键没有关系.(一张表值描述一件事情) 3.第三范式(3NF):满足2NF后,要求:

MVC实战之排球计分(一)—— 需求分析与数据库设计

一.需求分析: 这个程序是排球计分程序,其业务非常简单,具体如下: 1.本程序可以选择用户身份,通过不同角度记录比赛分数. 2.不同身份记录的比赛成绩将会存储在不同的数据表(目前适合运动员和观众使用). 3.用户键入数据后,可以继续对数据进行操作(如:删除.修改.查看详情). 4,不同的身份的用户 ,不能修改非己的数据.只能修改自己的数据. 这个项目的用例图如下: 数据库设计:设计数据表之前,首先进行实体和关系的识别与确定.通过需求分析,可以观察得出,本项目的实体有:观众,运动员.(观众可以修改

02-大鸭梨博客系统数据库设计及Dapper的使用

毫无疑问,数据库的设计在一个系统中起了至关重要的作用.我们都知道,系统设计分为两部分,或者说是两个阶段,即数据库设计和功能设计.构建一个完善的系统需要这两个阶段的充分考量.周密设计.合理联接以及密切配合.数据库设计是整个系统的根基,它关乎系统功能的实现.稳定性.扩展性等多个方面,可见数据库设计的重要性. 那么好的数据库设计应该具备什么样的基本条件呢,大致有这么几点: 1.充分体现系统的需求 不管是数据库设计还是功能设计,我们最终的目的都是要实现客户的业务需求,所以数据库设计的第一准则就是要符合业

学生信息管理系统1(数据库设计篇)

1.系统概述 本次是做一个学生管理系统,在学了数据库之后,希望通过这个系统把所学知识应用与实际项目中去.加强自己的熟练程度. 开发背景:具备数据库,C#的相关知识储备,掌握基本的html知识. 用途:仅作练习用.通过一门语言,将数据库展现出来. 2.功能需求分析 系统概念层设计:功能用例图如下 1. 登录功能:用于身份认证 2. 数据操作:信息查询,数据的增删改.a) 数据操作里,管理员具备所有的操作权限.学生具有选课和查看的功能.以及可以修改自己的个人信息.3. UI设计 3.数据库设计 E-

数据库设计【笔记】

数据库设计 一.设计步骤   1.收集信息(来源项目需求分析)   2.标识实体(一般是需求分析中需要管理的信息名词)   3.标识每个实体的属性   4.实体之间的关系二.画e-r图(实体关系图)   1.矩形表示实体   2.椭圆表示实体的属性   3.菱形表示实体之间的关系   4.用直线连接实体和属性,实体和实体之间的关系三.实体之间的关系:   1.一对一  1:1          车和车位   2.一对多  1:N (1:M) 客人和客房   3.多对多  N:M