暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

侯正奇:数据库设计实操案例分享

百联云通 2021-05-07
1851

实践出真知,真正的理解来自于应用场景的实操。

我的分享不是课本常识,没有指导性意义,通过我的体验表达我理念,希望起到抛砖引玉的作用。

关于数据库设计,还得从数据库设计的基本步骤说起,做过开发的大都熟悉,但是不是按步骤操作的,就要根据项目的实际情况而定,反正我是比较随意的,像制ER图,小项目我就基本简化了,因为理解需求就可能直接给出要构建的关系、关系的属性以及其上的约束。但遇到大中型项目,就真得按标准来。我这里还是把数据库设计的几个标准化步骤列出来,否则显得太不专业。

1、需求分析:需求收集和分析,得到数据字典和数据流图;

2、概念结构设计:对用户需求综合、归纳与抽象,形成概念模型,用E-R图表示;

3、逻辑结构设计:将概念结构转换为某个DBMS所支持的数据模型(我们使用的是MySQL);

4、数据库物理设计:为逻辑数据模型选取一个最适合应用环境的物理结构;

5、数据库实施:建立数据库,编制与调试应用程序,组织数据入库,程序试运行;

6、数据库运行和维护:对数据库系统进行评价、调整与修改。

这些标准步骤和具体要求,也说明数据库的设计实际上是一门综合性很强的技术工作,应该是项目的核心技术人员把关。

最近由于技术资源紧缺,而且设计理念上的共识性不够,我决定亲自操持,进行了深入的技术分析以及实际操作,体会很深。庆幸我的及时介入,很快就找到了我们项目中的几个关键问题,跟数据库设计有较大的关系,先拿出来作为前奏。

一、 复杂的供应链费用体系设计

费用系统的独立性意义重大,费用体系是国际物流中核心服务能力的体现,是资源整合能力的象征,是国际物流互联网电商的灵魂,但可能是传统业务的绊脚石和鸡肋。
费用系统应该与核心业务系统(ERP)解耦,让后台业务系统可以脱离费用系统处理所有业务类型(包括传统线下业务)的可能性;
新的设计方案是创建一个计算公式和计算方式表,关联统一的费用表,根据不同的供应商、业务类型自动匹配计算方式和计算公式。可以较大程度减少维护难度,增加系统设计的科学性。特别是考虑为同行赋能,建立各自费用体系和各自服务资源的可能性。

二、 通用业务类型处理方式

通过对海、陆、空,进、出口,拼箱及整箱的数据项抽象分析,获得统一解决方案。采用配置化处理不同业务类型,可以满足业务类型的无限增加。因此,我们的所有拼箱业务要尽快上线,才符合专业拼箱平台的品牌推广,而技术实现不是主要问题。如果脱离电商前端,业务后台还可以满足整箱操作。如果满足全业务类型,就具备ERP处理能力,就有了对同行与合伙人的整合能力。

三、 明确微服务部署

这不是赶时髦,我有丰富的单体架构经验,也一直在分析微服务与单体架构的优缺点,微服务是我们平台发展的客观需要。同行的深度参与是必然,还有必要考虑SaaS架构(数据库设计也要考虑分库分表);业务系统与电商系统的充分解耦,更适合传统线下业务的正常开展,以及帮助传统企业的数字化升级转型(或者说是摆脱传统ERP系统)。一定要考虑核心系统的独立性、专业性和扩展性,但不是泛微服务,要有合理的边界。

四、 深刻感受技术开发不能主导产品设计

产品设计是迎合用户需求的,也代表了公司战略和决策。而开发者重视的是功能的实现,相对忽视用户体验和应用场景。三分之一以上的产品设计者是UI美工出身,产品设计可以不需要理解技术,理解需求才是根本,(公司甚至要求设计出像打游戏一样的产品,这样的产品设计者一定是美工出身)。所以,产品经理遵从的原则是满足需求,设计优质产品,允许不考虑技术实现,管理者可以根据团队技术能力再调整产品设计。为开发人员设计的产品都是给自己定制、挖坑,技术人会告诉我们许多实现的功能都埋在不为人知的深处,会把许多他们认为麻烦的、系统缺陷的、系统设计欠考虑的问题挡回去,他们说什么都是对的,否则,就不会响应产品的需求,以种种理由拒绝执行,这是本末倒置的。所以说,数据库设计一定是基于产品设计的需求,因为产品经理是对需求最了解的人之一。

以上几个方面的理解和解决方式,可以说是取得突破性的研究结果(说成果有点过分)。

下面,具体谈一下数据库的设计理念,探讨我们提高数据库设计的能力。

数据库设计应该与应用系统设计高度结合,一般的软件工程忽视对应用中数据语义的分析和抽象,只要有可能就尽量推迟数据结构设计的决策,致力于数据模型和建模方法,忽视了对行为的设计,特别是系统结构的整体性分析不够,导致数据库设计基本上只体现在技术层面。而数据库设计实际上是:二分技术,八分管理,这是我根据自己的经验,对数据库管理给的最高定论。

我之所以认为数据库设计是身兼系统分析师和架构师的工作,原因是大型系统对数据库设计的要求相当高(质量与经验有直接的关系)。

首先,在需求收集和分析这个阶段,就必须对业务有深刻的、全面的理解,不但是理解业务的本身,更重要的是对涉及的整个行业和相关外围环境的理解,否则,只会得到片面的业务需求,被动的停留在具体业务应用的层面,导致系统的整体性受到局部思维的限制,得到的数据字典和数据流图都会受到需求理解的限制。类似于我们做海运出口拼箱系统,由于之前对整个国际物流缺乏全面理解,无法获知同行业其它业务类型的需求,导致系统局限于单一的业务类型,限制了系统的扩展性。下图是我对国际物流这个行业的理解后做的背景分析。


通过我绘制的这张图可以让大家明白,不管是海陆空、还是进出口、拼箱与整箱,业务流程基本相同,也就是说,在设计数据库的时候,所有业务类型的80%以上的数据项是相同的,业务类型的增加不需要系统的重构和再造。

对行业背景的了解至关重要,这有利于系统架构师、数据库设计师的全局思维分析,以及系统的扩展设计,对于一个高质量的数据库设计是很重要的。现实的应用往往是复杂的,又有谁能够理解应用所有的数据需求并直接给出最终的数据库设计呢?

当然,对业务流程的熟悉是最基本的要求,这方面,数据库设计和产品设计要保持高度一致。我在这张早期绘制的流程图上实际花的功夫不少,但基本上使我了解完整的业务流程,才有了数据库设计和架构设计的底气。



需求搞完了,进入数据库设计的概念结构设计阶段。

一般大中型项目的数据库设计,ER图是必须步骤,有必要花点时间创建ER图表和数据字典,其中应该包含每个字段的数据类型和在每个表内的主外键。做 ER 图和数据字典确实有点费时,但对其他开发人员要了解整个设计却是完全必要的,不是你一个人掌握了就行,要让整个团队成员都理解。当然,某些人会乐意于独自控制,也有某些人会乐意于被动接受工作,你说怎么做我就怎么做。要让任何参与开发的人都明确如何从数据库中获得数据,团队效率才会高。

ER图表的重要性如何强调都不过分,这对确定数据表之间关系很有用,一张图表胜过千言万语,开发人员不仅要阅读和实现它,而且还要用它来帮助自己和用户(业务部门)对话。这也是一种工作模式,有助于提高协作效能。将各局部应用涉及的数据分别从数据字典中抽取出来,ER参照数据流图,标定各局部应用中的实体、实体的属性、标识实体的码;确定实体之间的联系及其类型。

下面是订单管理子系统的分E-R图设计实例:

订单管理子系统的主要功能:

1、处理客户或同行的询价单并转订单;

2、系统是根据订单安排后续服务的;

3、服务完成才开出发票,付款后发提单;

4、收到付款后或满足账期协议,进行应收款、账单处理。

逐一设计分E-R图,数据库的脉络就清晰的呈现。E-R图设计的两条规矩要了解清楚,一是属性不能再具有需要描述的性质。就是说,实体的属性必须是不可再细分的数据项,不能再由另一些属性组成;二是属性不能与其他实体有联系,联系只发生在实体之间。



上图是ER粗略图,但我更习惯下面这样做,解决同样的问题但效果可能不一样,也取决于与不同的团队沟通。


设计人员应充分考虑到可能的扩充和改变,使设计易于更改,系统易于扩充 。重视数据结构的设计分析是构造复杂软件系统的基础,其核心就是分解与抽象。所以,数据库设计一般是核心技术人员把关。

没有系统性研究过数据结构或者没有开发过对程序效率要求较高的程序员,对数据关联性的认知不足。当程序功能有限,数据量不多的时候,没有什么问题,但一旦系统功能复杂,数据量增加,系统的风险性非常大,迭代升级非常麻烦。我衡量一个优秀程序员的标准,就是分析他的数据表设计和数据逻辑结构。

概念结构设计的优点:能真实、充分地反映现实世界;易于理解;易于更改;易于向关系、网状、层次等各种数据模型转换。在多层的数据流图中选择一个适当层次的数据流图,作为设计分ER图的出发点,通常以中层数据流图作为设计分ER图的依据,我这里是以用户询价为出发点。



在这之间,我基本上会做一张全局数据流图,但忽略分级数据流图,数据流图绘制简单,因为本身只是概念性的表达数据的流向。

概念设计也是理解架构的思维方式,我一向采用自顶向下的方法,就是定义全局概念结构的框架,然后逐步细化。其次是逐步扩张的方法,首先定义最重要的核心概念结构,然后向外扩充,以递增方式逐步生成其他概念结构,直至总体概念结构。

随着微服务、SaaS、数据中台的流行,数据库的结构关系复杂多了。

数据库设计中的概念结构是对现实世界的一种抽象。

关于数据抽象的问题,举一个实践案例,我们的业务类型包括:海运出口、空运出口、铁运出口和海运进口、空运进口、铁运进口出口,既然是同一个行业,必定有显著的共性,就看抽象到哪一个层次。数据设计的抽象,也决定了业务系统的设计,如果试图用6套系统来解决同一个问题,显然是缺乏对数据抽象的理解。



这是我做的抽象分析表, 100多数据项,共性达80%以上。

还有一个例子,就是我们的费用体系构建。该费用体系是由供应链上众多的供应商的协议费用构成,每个订单包括多项费用,不同的服务项、不同的港口有不同的费用计算公式,与客户的协议费用也是与不同的服务和不同的港口关联,而且供应商的费用数据格式不同、费用计算方式不同,如果不采取抽象数据攫取的方式和理念,就会导致大量数据表的存在,数据维护和系统开发的难度大了许多。

抽象是对实际的人、物、事和概念中抽取所关心的共同特性,忽略非本质的细节,并把这些特性用各种概念精确地加以描述。我们常用的抽象包括这三种:分类、聚集、概括。从以上案例就可以看出,我们的系统设计思想没有很好的发挥抽象思维,被非本质的细节约束了。

数据库设计是一门很深的学问,我也只懂一些日常操作上的知识,只不过经历较多。

数据库的物理设计、实施和维护就不多讲了,我认为是系统集成的工作,像容灾备份、负载均衡等。这里只是分析数据库设计的科学性与合理性,以及对整个系统的意义。

总的来说,数据库设计是一个系统的工程,是一个复杂的过程,需要对整个系统都有详细的了解才能做好。

文中所有图表都是我在本项目中的实操,所以,文章定义为实操分享。



文章转载自百联云通,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论