龙岩做网站开发哪家做的好,网页版梦幻西游大闹天宫八卦炉,域名服务器有哪些,百度公司网站seo方案SQL反模式一书在附录章节给出了设计关系数据库的规范化规则#xff0c;一个简明的规范化规则清单。 关系是什么 在规范化之前#xff0c;我们先要理解下关系。 数学中关系定义#xff1a;两个不同数据域上的值的集合#xff0c;通过一个条件得到的一个所有可能组合的子集。…SQL反模式一书在附录章节给出了设计关系数据库的规范化规则一个简明的规范化规则清单。 关系是什么 在规范化之前我们先要理解下关系。 数学中关系定义两个不同数据域上的值的集合通过一个条件得到的一个所有可能组合的子集。 怎么理解呢书中以棒球队和城市举例比如有一个包含所有棒球队的集合还有一个包含所有城市的集合 如果把每个城市和每个球队随意组合进行列表列表会很长但其实我们只需要关注“球队和其所属城市的集合”。 所以“关系” 作为一种规则比如城市是指某一支队伍所属城市“过滤子集的规则然后将这个子集存储在数据库一张表中关系即表示的是表中列与列之间的关系。 数据库表需要满足以下条件 行之间没有上下顺序列之间没有左右顺序重复记录不允许每一列只有一个类型每一行只有一个值列中都是数据值而不是物理存储标识如Oracle的ROWNUM伪列等规范化的神话 以下一些对规范化的理解是错误的 规范化让数据库更慢不规范让数据库更快规范化就是把数据移到子表之中规范化就是将属性尽可能的拆分开没人需要超过第三范式的规范化标准很久以前我也是这么认为的现在经过项目实践以及阅读SQL反模式这本书后这些观念都是不正确的比如不规范只能让某一种查询变快其他业务的查询可能呢个就很困难和很慢再比如不符合范式使得程序含有了隐藏的Bug。 规范化是保证我们正确的存储数据保证数据的完整性如果没有这个基础就不用谈其他的了。 什么是规范化 书中简明给出了规范化的目标如下 以一种我们能理解的方式表示事物减少数据的冗余存储防止异常或者不一致的数据支持完整性约束提供数据的性能并不在以上列表中但规范化本身保证数据的正确存储很多时候项目因为错误、不一致、重复的数据出现很多问题但如果一开始就进行规范化设计就会避免这些问题所以在某种程度是提升了效率。 范式 以前只了解一到四范式以及BCNF范式从本书了解到第六范式和DKNF范式一般的讲述都是以主键、候选键主属性、非主属性以及依赖关系来解释范式的这里了解到不同的解释。 第一范式 该表必须是一个关系满足前面关系中数据库表的条件表中没有重复组合并不是记录重复是指一行中可能有多个来自于同一个集合的值比如书中以产品缺陷管理举例如缺陷标签下面两个图都不满足第一范式。 第一个表tag1、tag2、tag3都是来自同一个集合tag 第二个表tags字段的值为多个值也是来自同一个集合tag 始终记住关系中的每一行都是从多个集合的每个集合中选一个值形成的组合 满足第一范式的如下图 第二范式 表中存在字段其取值与部分主键字段无关表中数据有冗余更新不当会造成数据异常。还是刚刚的缺陷标签表现在要往BugsTags表中增加打标签者以及标签创建者下图就不符合第二范式 tagger字段是打标签者coiner是标签创建者BugsTags表是bug_id和tag复合主键coiner只与tag有关与Bug是无关的即只依赖部分主键并且coiner取值是重复的所以不符合第二范式。 如果需要修改某个标签的创建者如果没有修改掉该表中所有tag为该标签的coiner就会出现数据不一致这种情况尤其可能出现在多个人同时修改该值的时候。 但是我这里有一个疑问这张表符合第一范式吗tagger和coiner字段都应该来账户集合如Account表有两列来自相同的集合应该不符合第一范式呢。除非理解标签创建者和打标签者属于不同集合。 而满足第二范式的设计是增加一个标签表tags如下图 第三范式 第二范式是存在字段只依赖于组合主键中的部分而第三范式是存在字段不依赖于任何主键而是依赖其他字段。 如果需要记录处理Bug的工程师的email下图的设计不符合第三范式 assigned_email与主键bug_id无关只由assigned_to这个非主键字段决定所以不符合第三范式assigned_email取值也是冗余的也会有更新问题。 符合第三范式的设计是应该把email放到Accounts表中email直接与主键关联没有冗余。如下图 BCNF博伊斯-科德范式 BCNF范式与第三范式的差异很细微在第三范式中所有非主键字段都必须直接依赖于这张表中的所有主键列而BCNF范式要求主键字段也必须遵循这个规则一般在一张表有复合主键时有效。 比如我们有三种Tag类型描述Bug所造成影响的tag描述Bug影响子系统的tag以及Bug修复状态的tag且要求每一个Bug对于每一种tag类型只能有一个tag所以这里可能的复合主键有bug_id加上tag或者复合主键为bug_id加上tag_type,这两种组合都可以定位到一行。 存在两种复合主键所以下图的设计就不符合BCNF 这里一个隐含的假设是不同tag_type下的tag是不同的且一个tag只属于一种tag_type如果没有这个假设bug_id加上tag是定位不到一行的。 按照这个假设以前面符合第二范式和第三范式的设计很项微妙的差别在于该字段在表中的作用是一般字段呢还是复合主键符合第三范式的设计如下图 第四范式 随着业务应用复杂度的提升比如需要支持多个用户报告同一个Bug并可以分配给多个开发工程师然后由多个质量工程师验证。这属于多对多的关系 所以我们需要额外的一张表如下图不符合第四范式 这里不能单独使用bug_id作为主键。每个Bug需要多行数据来实现各个字段都支持多个账号的目的主键需为bug_id、reported_by、assigned_to、verified_by的复合主键然而bug报告时是不需要立即进行分配和验证的所以assigned_to和verified_by需要可以为null而标准情况下主键是不能为null的。 另外的一个问题就是当报告问题者大于分派者或者大于验证者就会出现数据冗余。 所以当只用一个表描述多个多对多关系时就违背了第四范式正确的做法如下图 第五范式 任何满足BCNF范式并且没有复合主键的表将同时满足第五范式。 比如业务需要指定有些工程师只能为某些产品进行服务。 业务还需要了解哪些工程师在为哪些产品服务以及修复了哪些Bug下面的设计不符合第五范式 但这个表只说明了这个工程师当前指派去服务哪些产品它不能说明哪个工程是可以被指派为哪些产品服务 与第四范式一样也是在一张表中存储多种独立的多对多关系而产生的微妙的差别是没有null的情况。 bug_id与assigned_to是多对多的关系assigned_to与product_id是多对多的关系而bug_id与product_id应该假定是多对一关系存在Bugs表中每个Bug只属于一个product。 所以解决方案是把每个多对多关系放在一个表中如下 DK范式 DK范式涵盖了第三、四、五范式和BCNF范式。并认为表上的每个约束是这张表的数据域约束和主键约束的逻辑结果如何理解呢 比如状态为新建的bug应该是没有任何工作时间记录的也不需要指派验证工程师的一个做法是在状态这个非主键字段上建立触发器或者check约束来进行验证如果状态为新建没有值是允许的其他情况就不允许。但这种在非主键字段建议此约束的做法不符合DK范式。 第六范式 第六范式目标是消除所有的联结依赖通常用于支持记录字段取值的变更历史。 如Bug的状态随着时间推移产生变化任何发生的变更变更的时间谁做的变更以及其他可能的细节需要另一张表进行记录。 可以想象如果Bugs这张表需要满足第六范式则需要变更的列都需要附带一个历史记录表会导致表的数量过多多于大多业务来讲为每列变更都建立一个历史记录表是没有必要的在一些数据仓库技术中会使用到第六范式。 个人体会规范是为了减少数据冗余、提高数据的一致性必须的二、三、四、BCNF、五范式的差异很微妙随着业务系统的复杂度的提升需要考虑更高层次的范式。转载于:https://www.cnblogs.com/bwater/p/8203770.html