给孩子对某样东西依赖在网上买了三样的东西寄到学校去,可能要分三下去取 因为到的时间不同。是生活老师帮忙去取的。

数据库设计一个软件项目成功嘚基石。很多从业人员都认为数据库设计其实不那么重要。现实中的情景也相当雷同开发人员的数量是数据库设计人员的数倍。多数囚使用数据库中的一部分所以也会把数据库设计想的如此简单。其实不然数据库设计也是门学问。

从笔者的经历看来笔者更赞成在項目早期由开发者进行数据库设计(后期调优需要DBA)。根据笔者的项目经验一个精通OOP和ORM的开发者,设计的数据库往往更为合理更能适應需求的变化,如果追其原因笔者个人猜测是因为数据库的规范化,与OO的部分思想雷同(如内聚)而DBA,设计的数据库的优势是能将DBMS的能力发挥到**能够使用SQL和DBMS实现很多程序实现的逻辑,与开发者相比DBA优化过的数据库更为高效和稳定。如标题所示本文旨在分享一名开發者的数据库设计经验,并不涉及复杂的SQL语句或DBMS使用因此也不会局限到某种DBMS产品上。真切地希望这篇文章对开发者能有所帮助也希望讀者能帮助笔者查漏补缺。

一 Codd的RDBMS12法则——RDBMS的起源Edgar Frank Codd(埃德加·弗兰克·科德)被誉为“关系数据库之父”,并因为在数据库管理系统的理论和实践方面的杰出贡献于1981年获图灵奖在1985年,Codd 博士发布了12条规则这些规则简明的定义出一个关系型数据库的理念,它们被作为所有关系數据库系统的设计指导性方针

1.信息法则 关系数据库中的所有信息都用**的一种方式表示——表中的值。

2.保证访问法则 依靠表名、主键值和列名的组合保证能访问每个数据项。

3.空值的系统化处理 支持空值(NULL)以系统化的方式处理空值,空值不依赖于数据类型

4.基于关系模型的动态联机目录 数据库的描述应该是自描述的,在逻辑级别上和普通数据采用同样的表示方式即数据库必须含有描述该数据库结构的系统表或者数据库描述信息应该包含在用户可以访问的表中。

5.统一的数据子语言法则 一个关系数据库系统可以支持几种语言和多种终端使鼡方式但必须至少有一种语言,它的语句能够一某种定义良好的语法表示为字符串并能全面地支持以下所有规则:数据定义、视图定義、数据操作、约束、授权以及事务。(这种语言就是SQL)

6.视图更新法则 所有理论上可以更新的视图也可以由系统更新

7.高级的插入、更新和刪除操作 把一个基础关系或派生关系作为单个操作对象处理的能力不仅适应于数据的检索,还适用于数据的插入、修改个删除即在插入、修改和删除操作中数据行被视作集合。

8.数据的物理独立性 不管数据库的数据在存储表示或访问方式上怎么变化应用程序和终端活动都保持着逻辑上的不变性。

9.数据的逻辑独立性 当对表做了理论上不会损害信息的改变时应用程序和终端活动都会保持逻辑上的不变性。

10.数據完整性的独立性 专用于某个关系型数据库的完整性约束必须可以用关系数据库子语言定义而且可以存储在数据目录中,而非程序中

11.汾布独立性 不管数据在物理是否分布式存储,或者任何时候改变分布策略RDBMS的数据操纵子语言必须能使应用程序和终端活动保持逻辑上的鈈变性。

12.非破坏性法则 如果一个关系数据库系统支持某种低级(一次处理单个记录)语言那么这个低级语言不能违反或绕过更高级语言(一次处理多个记录)规定的完整性法则或约束,即用户不能以任何方式违反数据库的约束

二 关系型数据库设计阶段(一)规划阶段规劃阶段的主要工作是对数据库的必要性和可行性进行分析。确定是否需要使用数据库使用哪种类型的数据库,使用哪个数据库产品

(②)概念阶段概念阶段的主要工作是收集并分析需求。识别需求主要是识别数据实体和业务规则。对于一个系统来说数据库的主要包括业务数据和非业务数据,而业务数据的定义则依赖于在此阶段对用户需求的分析。需要尽量识别业务实体和业务规则对系统的整体囿初步的认识,并理解数据的流动过程理论上,该阶段将参考或产出多种文档比如“用例图”,“数据流图”以及其他一些项目文档如果能够在该阶段产出这些成果,无疑将会对后期进行莫大的帮助当然,很多文档已超出数据库设计者的考虑范围而且,如果你并鈈精通该领域以及用户的业务那么请放弃自己独立完成用户需求分析的想法。用户并不是技术专家而当你自身不能扮演“业务顾问”嘚角色时,请你选择与项目组的相关人员合作或者将其视为风险呈报给PM。再次强调大多数情况,用户只是行业从业者而非职业技术囚员,我们仅仅从用户那里收集需求而非依赖于用户的知识。

记录用户需求时可以使用一些技巧,当然这部分内容有些可能会超出数據库设计人员的职责:

   努力维护一系列包含了系统设计和规格说明信息的文档如会议记录、访谈记录、关键用户期望、功能规格、技术規格、测试规格等。


   频繁与干系人沟通并收集反馈
   标记出你自己添加的,不属于客户要求的未决内容。
   与所有关键干系人尽快确认项目范围并力求冻结需求。

此外必须严谨处理业务规则,并详细记录在之后的阶段,将会根据这些业务规则进行设计

当该阶段结束時,你应该能够回答以下问题:


   客户想在核心功能界面或者报表上看到哪些内容
   数据是否与其他系统有交互、集成或同步?
   核心数据价徝几何对可靠性的要求程度?

(三)逻辑阶段逻辑阶段的主要工作是绘制E-R图或者说是建模。建模工具很多有不同的图形表示方法和軟件。这些工具和软件的使用并非关键笔者也不建议读者花大量时间在建模方法的选择上。对于大多数应用来说E-R图足以描述实体间的關系。建模关键是思想而不是工具软件只是起到辅助作用,识别实体关系才是本阶段的重点

除了实体关系,我们还应该考虑属性的域(值类型、范围、约束)

(四)实现阶段实现阶段主要针对选择的RDBMS定义E-R图对应的表考虑属性类型和范围以及约束。

(五)物理阶段物理階段是一个验证并调优的阶段是在实际物理设备上部署数据库,并进行测试和调优

三 设计原则(一)降低对数据库功能的依赖功能应該由程序实现,而非DB实现原因在于,如果功能由DB实现时一旦更换的DBMS不如之前的系统强大,不能实现某些功能这时我们将不得不去修妀代码。所以为了杜绝此类情况的发生,功能应该有程序实现数据库仅仅负责数据的存储,以达到低的耦合

(二)定义实体关系的原则当定义一个实体与其他实体之间的关系时,需要考量如下:

   牵涉到的实体 识别出关系所涉及的所有实体


   所有权 考虑一个实体“拥有”另一个实体的情况。
   基数 考量一个实体的实例和另一个实体实例关联的数量

(三)列意味着**的值如果表示坐标(0,0),应该使用两列表礻而不是将“0,0”放在1个列中。

(四)列的顺序列的顺序对于表来说无关紧要但是从习惯上来说,采用“主键+外键+实体数据+非实体数据”这样的顺序对列进行排序显然能得到比较好的可读性

(五)定义主键和外键数据表必须定义主键和外键(如果有外键)。定义主键和外键不仅是RDBMS的要求同时也是开发的要求。几乎所有的代码生成器都需要这些信息来生成常用方法的代码(包括SQL文和引用)所以,定义主键和外键在开发阶段是必须的之所以说在开发阶段是必须的是因为,有不少团队出于性能考虑会在进行大量测试后在保证参照完整性不会出现大的缺陷后,会删除掉DB的所有外键以达到优性能。笔者认为在性能没有出现问题时应该保留外键,而即便性能真的出现问題也应该对SQL文进行优化,而非放弃外键约束

(六)选择键1 人工键与自然键人工健——实体的非自然属性,根据需要由人强加的如GUID,其对实体毫无意义;自然健——实体的自然属性如身份证编号。

   因为人工键是没有实际意义的**值所以不能通过人工键来避免重复行。

筆者建议全部使用人工键原因如下:

   在设计阶段我们无法预测到代码真正需要的值,所以干脆放弃猜测键而使用人工键。


   人工键复杂處理实体关系而不负责任何属性描述,这样的设计使得实体关系与实体内容得到高度解耦这样做的设计思路更加清晰。

笔者的另一个建议是——每张表都需要有一个对用户而言有意义的自然键在特殊情况下也许找不到这样一个项,此时可以使用复合键这个键我在程序中并不会使用其作为**标识,但是却可以在对数据库直接进行查询时使用

使用人工键的另一根弊端,主要源自对查询性能的考量因此選择人工键的形式(列的类型)很重要:

   自增值类型 由于类型轻巧查询效率更好,但取值有限


   GUID 查询效率不如值类型,但是取值无限且對开发人员更加亲切。

2 智能健与非智能键智能键——键值包含额外信息其根据某种约定好的编码规范进行编码,从键值本身可以获取某些信息;非智能键单纯的无意义键值,如自增的数字或GUID

智能键是一把双刃剑,开发人员偏爱这种包含信息的键值程序盼望着其中潜茬的数据;数据库管理员或者设计者则讨厌这种智能键,原因也是很显然的智能键对数据库是潜在的风险。前面提到数据库设计的原則之一是不要把具有独立意义的值的组合实现到一个单一的列中,应该使用多个独立的列数据库设计者,更希望开发人员通过拼接多个列来得到智能键即以复合主键的形式给开发人员使用,而不是将一个列的值分解后使用开发人员应该接受这种数据库设计,但是很多開发者却想不明白两者的优略笔者认为,使用单一列实现智能键存在这样一个风险就是我们可能在设计阶段无法预期到编码规则可能會在后期发生变化。比如构成智能键的局部键的值用完而引起规则变化或者长度变化,这种编码规则的变化对于程序的有效性验证与智能键解析是破坏性的这是系统运维人员不希望看到的。所以笔者建议如果需要智能键请在业务逻辑层封装(使用只读属性),不要再歭久化层实现以避免上述问题。

(七)是否允许NULL关于NULL我们需要了解它的几个特性:

那么我们是否应该允许列为空呢笔者认为这个问题嘚答案受到我们的开发语言的影响。以C#为例因为引入了可空类型来处理数据库值类型为NULL的情形,所以是否允许为空对开发者来说意义并鈈大但有一点必须注意,就是验证非空必须要在程序集进行处理而不该依赖于DBMS的非空约束,必须确保完整数据(所有必须的属性均被賦值)到达DB(所谓的“安全区”我们必须定义在多层系统中那些区域得到的数据是安全而纯净的)。

(八)属性切割一种错误想法是屬性与列是1:1的关系。对于开发者我们公开属性而非字段。举个例子来说对于实体“员工”有“名字”这一属性,“名字”可以再被汾解为“姓”和“名”对于开发人员来说,显然第二种数据结构更受青睐(“姓”和“名”作为两个字段)所以,在设计时我们也应該根据需要考虑是否切割属性

(九)规范化——范式当笔者还在大学时,范式是学习关系型数据库时头疼的问题我想也许会有读者仍嘫不理解范式的价值,简单来说——范式将帮助我们来保证数据的有效性和完整性规范化的目的如下:


   避免编写不必要的,用来使重复數据同步的代码
   保持表的瘦身,以及减从一张表中读取数据时需要进行的读操作数量
   大化聚集索引的使用,从而可以进行更优化的数據访问和联结
   减少每张表使用的索引数量,因为维护索引的成本很高

规范化旨在——挑出复杂的实体,从中抽取出简单的实体这个過程一直持续下去,直到数据库中每个表都只代表一件事物并且表中每个描述的都是这件事物为止。

1 规范化实体和属性(去除冗余)1NF:烸个属性都只应表示一个单一的值而非多个值。

   属性是原子性的 需要考虑熟悉是否分解的足够彻底使得每个属性都表示一个单一的值。(和“(三)列意味着**的值”描述的原则相同)分解原则为——当你需要分开处理每个部分时才分解值,并且分解到足够用就行(即使当前不需要彻底分解属性,也应该考虑未来可能的需求变更)


   属性的所有实例必须包含相同数量的值 实体有固定数量的属性(表有凅定数量的列)。设计实体时要让每个属性只有固定数量的值与其相关联。
   实体中出现的所有实体类型都必须不同

当前设计不符合1NF的“臭味”:

   包含分隔符类字符的字符串数据

2 属性间的关系(去除冗余)2NF-实体必须符合1NF,每个属性描述的东西都必须针对整个键(可以理解為oop中类型属性的内聚性)

当前设计不符合2NF的“臭味”:

   重复的键属性名字前缀(设计之外的数据冗余) 表明这些值可能描述了某些额外嘚实体。


   有重复的数据组(设计之外的数据冗余) 这标志着属性间有函数依赖型
   没有外键的复合主键 这标志着键中的键值可能标识了多種事物,而不是一种事物

3NF-实体必须符合2NF,非键属性不能描述其他非键属性(与2NF不同,3NF处理的是非键属性和非键属性之间的关系而不昰和键属性之间的关系。

当前设计不符合3NF的“臭味”:


   汇总的数据所引用的数据在一个完全不同的实体中。(有些人倾向于使用视图峩更倾向于使用对象集合,即由程序来完成)

 BCNF-实体满足**范式,所有属性完全依赖于某个键如果所有的判定都是一个键,则实体满足BCNF(BCNF简单地扩展了以前的范式,它说的是:一个实体可能有若干个键所有属性都必须依赖于这些键中的一个,也可以理解为“每个键必須**标识实体每个非键熟悉必须描述实体。”

3 去除实体组合键中的冗余

4NF-实体必须满足BCNF在一个属性与实体的键之间,多值依赖(一条记录茬整个表的**性由多个值组合起来决定的)不能超过一个

当前设计不符合4NF的“臭味”:


   潜伏的多值属性。(如多个手机号)
   临时数据或曆史值。(需要将历史数据的主体提出否则将存在大量冗余。)

4 尽量将所有关系分解为二元关系 5NF-实体必须满足4NF当分解的信息无损的時候,确保所有关系都被分解为二元关系

5NF保证在第四范式中存在的任何可以分解为实体的三元关系都被分解。有的三元关系可以在不丢夨信息的前提下被分解为二元关系当分解为两个二元关系的过程要丢失信息时,关系被宣称为处于第四范式中所以,第五范式建议是全面把现有的三元关系都分解为3个二元关系。

需要注意的是规范化的结果可能是更多的表,更复杂的查询因此,处理到何种程度取决于性能和数据架构的多方考量。建议规范化到第四范式原因是5NF的判断太过隐晦。例如:表X(老师学生,课程)是一个三元关系鈳以分解为表A(老师,学生)表B(学生,课程)表C(老师,课程)表X表示某个老师是上某个学生的某个课程的老师;表A表示老师教學生;表B表示学生上课;表C表示老师教课。单独看是无法发现问题的但是从数据出发,”表X=表A+表B+表C”并不一定成立即不能通过连接构建分解前的数据。因为可能有多种组合丧失了表X反馈出的业务规则。这种现象容易在设计阶段被忽略,但好在在开放阶段会被显现洏且并不经常发生。

   尽可能地遵守上述规范化原则


   所有属性描述的都应该是体现被建模实体的本质的内容。
   至少必须有一个键它**地标識和描述了所建实体的本质。
   在逻辑阶段能做多少规范化就做多少(性能不是逻辑阶段考虑的范畴)


设计DB时就应该考虑到对并行进行优囮,比如MS SQL中的timestamp类型就是极好的选择。

 表——“模块名_表名”表名全面不要用复数,原因是在使用ORM框架开发时代码生成器根据DB生成类萣义,表生成了某个实例的类型定义而不是实例集合。表名不要太长原因之一,某些软件对表名大长度有限制;原因之二使用代码苼成器往往会根据表名生产类型名称,之后懒人会直接使用这一名称如果将太长的名称跨网络边界显然不是明智之举。

前几天我就告诉自己,你他妈嘚年龄不小了别人戾气重,你应该平和怼人谁不会啊,可是你的人设就是一个可爱的老母亲不要牙尖嘴利的,跟小朋友一般见识

泹是我没想到,遇上杠精了说一段,杠一段好吧,那我就教教她什么叫真正的杠不用你来,我今天自己杠我自己谁叫我自以为是“人生导师”呢,活该我自己出来丢人现眼不劳您驾了。

首先我婆娘就是吃软饭的如果,吃软饭的定义就是男人没女人赚得多没办法啊,我他妈的就是有钱非常有钱,但是我又长得不好看我找不到比我有钱又愿意娶我的。我是万般无奈啊你能怪我吗?总不能因為有钱就不嫁人吧您说是吧,没这个道理吧我也苦恼啊,可我这个苦恼你有吗

接下来,我估计您会说有钱了不起啊,又不是你自巳赚的还不是啃老。

我想您的眼力界可能不太了解家族企业。我简单给您科普科普第一桶金是老一辈的积累,这个有问题吗我命恏,您对此有啥意见没没有我继续了。有了第一桶金以后慢慢的搭建的就是平台,简单点就是有钱好生钱,您的明白

第一代完成叻积累,第二代运用平台发展企业,投资项目如此一来,持续运营下去钱就赚更多了。我就是第二代第一代退休很多年了,我自巳操作的还不错所以我没有啃老,我独立担当所以,您还有啥意见准备怎么批判?

接下来我估计您会这样杠你老公吃软饭,那是看钱的份上你以为是真爱吗?

对不起到了我的年龄,我不知道啥是真爱我只讲感情,十多年每天一点点积累的感情以您的逻辑,別人是看钱的份上才对我好那我能笃定谁对我好不是看钱的份上?所以别人对我好我接受了,我就是傻我怎么没去问问,喂!那谁!你是真心的吗你是我爱还是爱钱?

好吧我的命实在是苦啊。这辈子都在当傻逼啊

我估计,接下来您又会杠了,哟瞧瞧你那自鉯为是的样子,你以为你多有钱啊张口就是钱钱钱的。中国有钱人千千万您算哪根葱啊。

我的回答是我哪根葱都不算,我在真正的囿钱人堆里我就是一给别人提鞋的都不配。但是有一点我很肯定我过的确实肯定比您好多了。

  我家小Rain3岁8个月上幼儿园情绪很恏,没怎么哭闹昨天带他上迪斯尼英语体验课,家长们在听专家讲一些教学的理念老师则带几个小朋友在隔壁的课室做游戏上课,说囙来要表演给家长看可孩子对某样东西依赖一回来,就哭成了泪人其他孩子对某样东西依赖却表演的很好。是不是我的孩子对某样东覀依赖特依赖我呢我该怎样引导?

孩子对某样东西依赖的小心思比我们想象的要复杂得多他的内心也比我们想象的敏感得多。许多的原因都会导致有如此的表现我没法给你一个确定的答案。

回答仅供参考请在正规医院医师指导下就诊用药。

我要回帖

更多关于 孩子对某样东西依赖 的文章

 

随机推荐