Rumah > Artikel > pangkalan data > 我所遵守的11条数据库设计准则
前言:作者Shivprasad koirala,前微软ASP/ASP.NET的MVC工程师,现于印度任CEO职位。学生初次翻译,如有不妥,不吝赐教。 简介 在你开始阅读这篇文章之前,我要先告诉你我不算是数据库设计方面的什么大师。下面的11条准则,是我从项目、从我自身的经验和我自
前言:作者Shivprasad koirala,前微软ASP/ASP.NET的MVC工程师,现于印度任CEO职位。学生初次翻译,如有不妥,不吝赐教。
在你开始阅读这篇文章之前,我要先告诉你我不算是数据库设计方面的什么大师。下面的11条准则,是我从项目、从我自身的经验和我自己的理解和学习中得来的。我个人认为在数据库设计方面运用这些准则能使我受益匪浅。我也欢迎任何批评与指点。
我之所以要写这么一篇详尽的文章,是因为,许多开发者设计数据库的时候十分信奉“三个范式”(译者注:而没有结合实际情况)。他们认为三范式是数据库设计的唯一真谛。随着项目开发的不断推进,持有这些想法的人会经常碰壁和遇上无穷无尽的麻烦。
如果你还不太了解什么是范式,可以点击这里:3 normal forms: part1-part2-part3(译者注:原文为yotube视频,由于众所周知的原因国内无法观看,我已将原视频分享到csdn下载区,下载免积分),这个教程将会手把手教你这三个范式。
“范式”是非常重要的准则,但是如果完全一味的遵守,不做丝毫改变的话,会让你经常陷入麻烦之中。当我设计数据库时,我将下面这11条重要的准则牢牢记在心中。(译者注:联机事务处理或联机分析处理,即偏向于增删改查还是偏向于数据分析)
当你开始设计数据库的时候,所要做的第一件事是分析你设计的应用的本质,是事务型呢还是分析型呢。你会发现,许许多多的开发者根本没有考虑自己的应用到底是属于哪种类型,而是全部按照“范式”的准则来设计,然后就碰上了各种各样的性能和定制的问题。正如我所说,有两种应用:基于事务型的和基于分析型的,那么接下来让我们了解一下这两种类型具体是什么。
事务型:这种类型的应用,最终用户对增删改查更为关注,比如,增加、读取、更新和删除记录。对于这种类型的数据库,正式来说我们称呼为OLTP(译者注:Online Transaction Processing,联机事务处理)。
分析型:这种类型的应用,最终用户更关注与对数据的分析、产生报告和对数据的预测等。这种类型的数据库很少执行插入或是更新数据的操作。这种设计的主要意图是以最快的速度从数据库获取数据,并进行分析。对于这种类型的数据库,正式来说我们称呼为OLAP(译者注:Online Analytical Processing,联机分析处理)。
换句话说,如果你发现在数据库上进行插入、更新或删除更为重要,那你应该遵循标准的范式来设计,否则应该建立一个扁平非规范的数据库结构。
下图展示了如何在左侧姓名和地址表中运用非规范化设计思想,来创建右侧的不遵守标准范式的扁平的非规范数据结构。
这条准则实际上就是第一范式。违背了这条准则的一个明显特征是,你的查询语句中用了一大堆字符串解析函数,如substring、charindex等。如果的却是这样,那么你需要应用一下这条准则。
举个例子,下图表中有个字段是“Student Name”,如果你想要查询名字中带有"Koirala"而不带有"Harisingh"的学生,你可以想象到时候你写出来的查询语句是什么样的。
所以一个更好的方案是将这个字段分解成更详细的逻辑片段,这样我们就能写出更干净,也更完美的查询语句了。
开发人员们都是聪明人。如果你告诉了他们一个门路,那么他们就总是使用这个方法。准则2用过头会导致一些你根本不想要的结果。但是准则2本身是非常有用的。当你想着"把这玩意儿拆了"的时候,暂停一下,问问你自己,真有必要拆吗?正如我刚才所说,拆分必须是逻辑性的。
举个例子,你可以看到下图中有个电话号码的字段,你几乎不会对号码的ISD(International Subscriber Dialing,国际订户拨号)分别进行管理(除非哪个项目里真有这个需求),所以就这么把号码放着显然更明智。要是你真的把它们拆了,那到时候你就得面对一大堆的"拆分后遗症"了。
小心冗余数据,并重构它们。我并不担心冗余数据会占用很多磁盘空间,我所担心的是这些冗余数据所造成的困惑与混乱。
比如说,在下图中,你会发现“5th Standard”和“Fifth standard”是一个意思,只不过描述的形式略微不同。你可能会解释说,这些数据是之前有人乱录入的,而且还没有经过验证。当你打算导出一个报告的时候,对于这个字段将产生两份不一样的报告,当用户看到这样的报告,他们恐怕就要在风中凌乱了。
一个解决办法就是,把这些数据移到一个新表中,然后原来的表以引用的方式使用这些数据。下图中你可以看到,我创建了一个新的叫做"Standards"的表,然后用一个外键将这两个表连接起来。
第一范式的第二条内容规定了一个位置上不能存多个值。下图就是一个存了多个值的例子。仔细观察"Syllabus"字段就会发现,我们塞了太多的数据到这个字段中了。这种字段我们成为"重复组",如果我们要操作这些数据,不仅查询语句会写的很复杂(且不论对错),而且我很怀疑这种查询的效率。
这种某些列里塞了很多数据的字段,要特别小心的对待,一个比较好的解决办法是:将这些字段移到不同的表中,然后将它们用外键相连,以便于从逻辑和操作上更好的进行管理。
我们需要遵守第一范式的第二条规定:一个位置不能存储多个值。从上图中可以看到,我建立了一个独立的"syllabus"表,然后与主表建立了多对多的关联。
用这种方法的话,主表中的"syllabus"字段不再塞入一大堆用分隔符分开的数据了。逻辑上易于理解,操作性也更强。
小心那些部分依赖于主键的字段,例如上图中的主键是Roll Number和Standard。现在来看看“syllabus”,这个字段与standard字段相关联,而不直接与Student(“Roll Number”字段)相关联。
“syllabus”字段与学生正在学习的"standard"字段相关联,而没有直接和学生关联。那么明天我想要更新“syllabus”的时候,我就必须把所有与之相关的"Student"字段也更新掉。老兄,这是个辛苦的体力活,而且还毫无逻辑!所以更有意义的做法是将"syllabus"字段单独拉出来然后与"Standard"通过外键关联。
你可以看到我是如何将"syllabus"字段拉出来然后与“Standards”相联系。
这条准则其实就是第二范式本身:所有的属性必须做到全部依赖,不应该有字段是部分依赖主键的。
如果你设计的是OLTP型数据库,即事务型数据库,避免派生列将会是很明智的,除非对这一块内容的性能有高要求。但是对于需要大量求和与计算的OLAP数据库,即分析型数据库,这些派生列就显得很有必要而且能使数据库性能更加优越。
上图中你可以看到,Average依赖Total Marks和Total Subject来计算,这就是数据冗余的表现之一。所以碰到这种派生于其他列的字段,要好好想一想,这个字段真的需要吗?
这条准则正如第三范式所说:字段不能依赖于任何非主键字段。我个人认为不要盲目遵循第三范式,要视情况而定。存在冗余的数据并不总是坏事。如果这些冗余数据是通过计算得来的,看情况来决定要不要遵守第三范式。
不要把"避免一切冗余数据"当成一条死命令。如果对性能的要求很高,就考虑一下非标准化吧。遵守标准的话,你经常需要使用join命令来连接很多个表格,但在非标准化中,通过设置一些冗余信息,就没那么多join命令了,所以性能会好得多。
使用OLAP(分析型)数据库的项目主要处理的是多维数据。举例来说的话你可以看一下下图,你想要得到每个国家的销量,每个顾客的销量和其他数据。简单来说,你所关注的销量是三个维度数据的交集。
这种情况下,设计成一个维度将会更好。简单来说,你可以建立一个拥有"sales amount"字段的销量表(它为中心表),然后设置一些外键来和其他的一维表相关联。
我经常会碰到键值表。键值表的意思是,它存储着键和和与这个键相对应的数据(译者注:就像数据结构中的map的用法一样,是一种结构相当简单的表)。举例来说,下表你可以看到有一个Currency 表和Country表,仔细观察就会发现,实际上这两张表中只有一个键和一个对应值而已。
对于这种类型的数据表,创建一个集中化的表然后设立一个"Type"字段来区分。这会使你的数据库工作的更好。
我也会经常会碰到多集数据的情况,考虑一个多级的销售方案,一个销售员旗下可以有很多个销售员。在这种情况下,引用自身的主键或是设立外键都会帮助你达到想要的效果。
这篇文章并不是让你不要遵守标准范式,而是让你不要盲目遵守,你要首先考虑的是项目的属性和你要处理什么类型的数据。
下面是一个用简单的学校表来手把手解释三个标准范式的视频(译者注:与上文中的“3 normal forms”为同一个视频,下载过的读者可不必重复下载)
SQL Server -- Can you explain First,Second and Third normal form in SQL server [part1]
SQL Server -- Can you explain First,Second and Third normal form in SQL server [part2]
SQL Server -- Can you explain First,Second and Third normal form in SQL server [part3]
(全文完)
原文来自:http://www.codeproject.com/Articles/359654/11-important-database-designing-rules-which-I-foll