数据库设计 Step by Step (1)

2019-03-02 23:55|来源: 网路

引言:一直在从事数据库开发和设计工作,也看了一些书籍,算是略有心得。很久之前就想针对关系数据库设计进行整理、总结,但因为种种原因迟迟没有动手,主要还是惰性使然。今天也算是痛下决心开始这项卓绝又令我兴奋的工作。这将是一个系列的文章,我将以讲座式的口吻展开讨论(个人偷懒,这里的总结直接拿去公司培训新人用)。

 

系列的第一讲我们先来回答下面几个问题

image

数据库是大楼的根基

大多数程序员都很急切,在了解基本需求之后希望很快的进入到编码阶段(可能只有产出代码才能反映工作量),对于数据库设计思考得比较少。

这给系统留下了许多隐患。许多软件系统的问题,如:输出错误的数据,性能差或后期维护繁杂等,都与前期数据库设计有着密切的关系。到了这个时候再想修改数据库设计或进行优化等同于推翻重来。

我经常把软件开发比作汽车制造。汽车制造会经过图纸设计,模型制作,样车制造,小批量试生产,最后是批量生产等步骤。整个过程环环相扣,后一过程是建立在前一过程正确的前提基础之上的。如果在图纸设计阶段发现了一个纰漏,我们可以重新进行图纸设计,如果到了样车制造阶段发现这个错误,那么我们就要把从图纸设计到样车制造的阶段重来,越到后面发现设计上的问题,所付出的代价越大,修改的难度也越大。

数据库是整个应用的根基,没有坚实的根基,整个应用也就岌岌可危了。

强大的数据库面对不良设计也无能为力

现代数据库管理系统(DBMS)提供了方便的图形化界面工具,通过这些工具可以很方便的创建表、定义列,但我们设计出的结构好吗?

关系数据库有许多非常好的特性,但设计不当会使这些特性部分或完全的丧失。

我们来看看以下几个数据库不良设计造成的场景:

1. 数据一致性的丧失

一个订单管理系统,维护着客户和客户下的订单信息。使用该系统的用户在接到客户修改收货地址的电话后,在系统的客户信息页面把该客户的收货地址进行了修改,但原先该客户的订单还是送错了地址。

2. 数据完整性的丧失

公司战略转移,准备撤出某地区。系统操作人员顺手把该地区的配置信息在系统中进行删除,系统提示删除成功。随后问题就来了,客服人员发现该地区的历史订单页面一打开就出错。

3. 性能的丧失

一个库存管理系统,仓库管理员使用该系统记录每一笔进出货情况,并能查看当前各货物的库存情况。在系统运行几个月后,仓库管理员发现打开当前库存页面变得非常慢,而且整个趋势是越来越慢。

上面这些场景都是由于数据库设计不当造成的,根源包括:设计时引入了冗余字段,没有设计合理的约束,对性能没有进行充足设计等,上面的例子也只是沧海一粟。

 

image

数据库平台无关性

我在这个系列博客里讨论的数据库设计不针对任何一个关系数据库产品。无论你使用的是Oracle,SQL Server,Sybase,亦或是开源数据库如:MySQL,SQLite等,都可以用来实践我们这里讨论的设计方法和设计理念,设计是这个系列博文的核心和灵魂。

注:在文中我会选用一个数据库产品来进行演示,大家可以选用自己熟悉的数据库产品来实验。本文最后会给出一些免费数据库产品的链接,大家可以下载学习。

一起学习共同进步

无论你是数据库设计师,应用架构师,软件工程师,数据库管理员(DBA),软件项目经理,软件测试工程师等项目组成员,都能从该系列博文中有所收获。大家一起讨论,共同进步。

内容涉及领域

我对这一系列博文现在的设想是涉及数据库设计的整个过程。从需求分析开始,到数据库建模(概念数据建模),进行范式化,直至转化为SQL语句。

 

image

在我们一头扎进数据库设计之前,我们先了解一下除了关系型数据库之外的数据存储方式。

平面文件(Flat File)

包括以.txt和.ini结尾的文件。

eg: 一个.ini文件的内容:

------------------------------------------------------------

[WebSites]

MyBlog=http://www.cnblogs.com/DBFocus

 

[Directorys]

Image=E:\DBFocus Project\Img

Text=E:\DBFocus Project\Documents

Data=E:\DBFocus Project\DB

------------------------------------------------------------

优点:

文件的存储形式非常简单,普通的编辑器都能对其进行打开、修改

缺点:

无法支持复杂的查询

没有任何验证功能

对平面文件中间的内容进行插入、删除操作其实是重新生成了一个新文件

适用场景:

存放小量,修改不频繁的数据,如应用配置信息

Windows注册表

错误的修改Windows注册表会引起系统的紊乱,故不建议把很多数据存放在注册表中。

Windows注册表为树形结构,存放着一些系统配置信息和应用配置信息。

通过把不同的配置存放在注册表的不同分支上,使得应用程序公共配置信息与用户个人配置信息分离。

eg:某文档版本管理系统,能通过配置与本主机上安装的文件比较器建立关联进行文档比较。这是一个公共配置信息,文件比较器路径可以存放在注册表的HKEY_LOCAL_MACHINE\SOFTWARE分支下。

同时该文档版本管理系统能记录用户最近打开的10个文档路径。这是用户个人配置信息,对于不同的Windows用户最近打开的10个文档可以不同,这些配置信息可存放在注册表的HKEY_CURRENT_USER\Software分支下。

Excel表单(Spreadsheets)

优点:

Excel 非常普及,用户对于Spreadsheet的表现形式非常熟悉

可以进行简单统计,方便出各种图表

缺点:

不适用于许多Spreadsheet之间关系复杂的情况

无法应对复杂查询

数据验证功能弱

适用场景:

数据量不是非常大的办公自动化环境

XML

XML是一种半结构化的数据。相比于超文本标记语言(HTML),其标签是可以自行定义的,即可扩展的。

eg:一个XML文件内容

-----------------------------------------------------

<?xml version=”1.0” encoding=”UTF-8” ?>

<ClassSchedule>

     <Class Name=“Psychology” Room=”Field 3”>

          <Instructor>Richard Storm</Instructor>

          <Students>

               <Student>

                     <FirstName>Ben</FirstName>

                     <LastName>Breaker</LastName>

               </Student>

               <Student>

                     <FirstName>Carol</FirstName>

                     <LastName>Enflame</LastName>

                     <NickName>Candy</NichName>

          </Students>

     </Class>

</ClassSchedule>

-----------------------------------------------------

XML文件有几个特点。

首先,XML标签要求严格对应,且不能出现交错的现象。

其次,XML文件必须有一个根节点,该节点包含所有其他元素。

第三,同级别的不同节点内不必包含相同的元素,如上例中第二个学生Carol有一个特别的节点NickName。这个特性使得在某些场景中XML比关系数据库更能应对变化。

优点:

自然的层次型结构

文本内容通过标签是自解释的

通过XSD(XML Schema语言)可以验证XML的结构

有许多辅助型技术如:XPath, XQuery, XSL, XSLT等

一些商业数据库(如Oracle,SQL Server)已支持XML数据的存储与操作

缺点:

数据的冗余信息较多

无法支持复杂的查询

验证功能有限

对XML中间的内容进行插入、删除操作其实是重新生成一个新文件

适用场景:

适合存放数据量不大,具有层次型结构的数据,如树形配置信息

NoSQL数据库

非关系型数据库我接触的不是很多,除了给出一些产品名称之外不做很多展开。园子里已有一些文章,本文最后也给出了链接供大家学习、研究。

1. Key-Value数据库

Redis, Tokyo Cabinet, Flare

2. 面向文档的数据库

MongoDB, CouchDB

3. 面向分布式计算的数据库

Cassandra, Voldemort

这几年NoSQL非常热。我认为NoSQL并不是“银弹”,在某些SNS应用场景中NoSQL显示了其优越性,但在如金融行业等对数据的一致性、完整性、可用性、事务性高要求的场景下,现在的NoSQL就未必适用。我们应充分分析应用的需求,非常谨慎地选择技术和产品。

image

主要内容回顾

1.数据库设计对于软件项目成功的关键作用

2.本课程与数据库产品无关,核心是设计的理念和方法

3.各种数据存储所适用的场景

参考资料

1. Oracle Database 10g Express Edition

2. SQL Server 2008 R2 Express – Overview

3. SQLite Home Page

4. NoSQL数据库笔谈


转自:http://www.cnblogs.com/aaa6818162/archive/2011/03/27/1997133

相关问答

更多
  • 我不认为get_context_data是执行此操作的正确方法; FormWizard是一个非常具体的类,它限制了您可以执行不同功能的位置。 指定FormWizard跳过某个步骤的典型方法是使用condition_dictionary 。 当条件(设置为callables)返回True时,Django使用该结构仅包含步骤的形式。 如果没有,那么该步骤的形式不会强制form.is_valid()从而绕过该步骤的验证。 这也确保了为每个步骤创建表单的所有隐藏管理信息。 这是一个如何工作的例子: # I alwa ...
  • 上述问题是由于对数据库的多次写入过程造成的。 我同步了数据库操作。 感谢您的建议。 The above problem is due to multiple write process to the DB. I synchronized the DB operations. Thanks for suggestions.
  • 在我看来,您需要使用此库的每种语言实现,以一致的格式写出数据。 例如,在C#中,您可能在javascript中的List中有数据,您可能在数组中拥有它。 这两种结构是不同的,如果没有lib来管理这个过程,就不能以相同的方式写出来。 它可行吗? 我想是这样。 但我不知道有任何图书馆这样做。 有趣的想法! It seems to me like you'd need to have a per language implementation of this library that wrote data out ...
  • 这意味着printf没有可用的源/调试符号。 无论如何,您可以使用stepi步进printf ,您只能使用反汇编(使用disas命令)。 This means there's no available source/debug symbols for printf. You can use stepi to step into printf anyway, you'll only have disassembly available (use the disas command).
  • 谷歌在其Android数据存储文档中有非常详细的说明。 Google has very detailed instructions to do this on it's Android Data Storage Documentation.
  • 请确保在“ Modified Java Script Value步骤的“输出字段”部分中使用您的变量。 这会将其添加为数据流中的列。 然后将此步骤连接到Execute SQL script步骤。 按照下图配置它,提供您自己的连接名称和表名称。 在此步骤中,我假设您将字段称为“DateField”,并且表中的列名为“datestamp”。 请注意,有很多方法可以做到这一点。 这是一种在变换中起作用的方式; 还有其他人也在为工作而工作。 Be sure you use your variable in the ...
  • 您可以向dataBound事件添加回调(每次将数据绑定到图表时触发),然后在此回调中您可以更改/设置step属性。 但是您需要从kendo图表中调用refresh方法才能应用更改。 代码类似于以下内容: //Your code .Events(ev => ev.RequestStart("viewModel.utilisationDataRequestStarted") .RequestEnd("uViewModel.utilisationDataLoaded"))) .DataBound("onDataB ...
  • 嗯...对不起,原谅我的愚蠢问题。 在我的环境中,PHP没有支持我的sql。 那是根源 Hm... sorry, forgive my silly question. In my enviroment, my sql has not been supported by PHP. That's the root
  • 不要重复课程。 让你的旧项目运行,并将它分叉到某个地方。 当然,使用单元测试和源代码控制。 然后,我会采用深度优先的方法,一次一点。 一次更改一个类以使其适应新的编码标准,并解决导致的所有编译器错误。 这尤其意味着对于您感兴趣的类,首先要删除旧的string.h ,更改接口和实现(字符串/向量类彼此没有区别),然后构建项目。 让编译器错误告诉你下一步该去哪里。 根据项目的大小,您可以从最少或最常用的类开始。 仅在转换了所有其他类之后删除未使用的字符串/向量类。 这可能是一个非常简单(虽然耗时)的操作(因此不 ...
  • 我们设计dfm()不是一个“黑匣子”,而是更像瑞士军刀,它结合了典型用户在将文本转换为文档和特征矩阵时想要应用的许多选项。 但是,如果您希望实现更精细的控制,则所有这些选项也可通过较低级别的处理命令获得。 然而, quanteda的设计原则之一是文本只通过标记化过程成为“特征”。 如果您要排除一组令牌化功能,则必须先将文本标记,或者不能排除它们。 与R的其他文本包(例如tm )不同,这些步骤从语料库“下游”应用,因此语料库仍然是将应用操作的未处理文本集(但本身不是一组经过转换的文本) 。 其目的是保持一般性 ...