1. 数据库的常见范式
目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、巴斯-科德范式(BCNF)、第四范式(4NF)和第五范式(5NF,还又称完美范式)。
在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
第一范式(1NF)—— 每一列原子不可分
在关系模型中,数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。
某个属性有多个值时,必须拆分为不同的属性。
有些关系模型中突破了1NF的限制,这种称为非1NF的关系模型。例如:Oracle表存放字符类型的列。
因此,是否必须满足1NF的最低要求,主要依赖于所使用的关系模型。
第二范式(2NF)—— 消除部分函数依赖
在第一范式(1NF)的基础上建立起来的,要求数据库表中的每个实例或行必须可以被唯一地区分,实体的属性完全依赖于主关键字,不能存在部分依赖(仅依赖主关键字一部分的属性)。
如果不符合2NF,这个选课关系表会存在如下问题:
(1) 数据冗余:同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
(2) 更新异常:若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
(3) 插入异常:假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
(4) 删除异常:假设一批学生已经完成课程选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
缺点
假定选课关系表为SelectCourse(学号, 姓名, 年龄, 课程名称, 成绩, 学分),关键字为组合关键字(学号, 课程名称),因为存在如下决定关系:
(学号, 课程名称) → (姓名, 年龄, 成绩, 学分)
这个数据库表不满足第二范式,因为存在如下决定关系:
(学号,课程名称) → (成绩)
(课程名称) → (学分)
(学号) → (姓名, 年龄)
即存在组合关键字中的字段决定非关键字的情况。
第三范式(3NF)—— 消除传递依赖(非主属性对主属性的)
在第一范式(2NF)的基础上建立起来的,要求一个数据库表中不包含已在其它表中已包含的非主关键字信息,即属性不依赖于其它非主属性。
例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在图3-2的员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。
巴斯-科德范式(BCNF)—— 消除传递依赖(所有属性对主属性的)
例如,假设仓库管理关系表为UserWarehouse(仓库ID,存储物品ID,管理员ID,数量),且有一个管理员只在一个仓库工作;一个仓库可以存储多种物品,则这个数据库表中存在如下决定关系:
(仓库ID,存储物品ID)->(管理员ID,数量)
(管理员ID,存储物品ID)->(仓库ID,数量)
所以,(仓库ID,存储物品ID)和(管理员ID,存储物品ID)都是UserWarehouse的候选关键字,表中的唯一非关键字段为数量,它是符合第三范式的。但是,由于存在如下决定关系:
(仓库ID)->(管理员ID)
(管理员ID)->(仓库ID)
即存在关键字段决定关键字段的情况,所以其不符合Boyce-Codd范式。为了符合Boyce-Codd范式,应当把仓库管理关系表分解为两个关系表:仓库管理表UserWarehouse(仓库ID,管理员ID)和仓库表Warehouse(仓库ID,存储物品ID,数量)。
第四范式(4NF)—— 消除传递依赖(非平凡且非函数依赖的多值依赖)
关系模式R∈1NF,如果对于R的每个非平凡多值依赖X→→Y(Y X),X都含有候选码,则R∈4NF。
(X→Y)
如果R ∈ 4NF, 则R ∈ BCNF
第五范式(5NF)——关系模式R中的每一个连接依赖均由R的候选码所隐含
完美范式。
2. 常见关系型和非关系型数据库
常用的关系数据库有Oracle,SqlServer,MySql,SyBase,Informix等。
常用的非关系数据库: NoSQL,泛指非关系型的数据库。
关系模型中常用的概念:
关系:可以理解为一张二维表,每个关系都具有一个关系名,就是通常说的表名
元组:可以理解为二维表中的一行,在数据库中经常被称为记录
属性:可以理解为二维表中的一列,在数据库中经常被称为字段
域:属性的取值范围,也就是数据库中某一列的取值限制
关键字:一组可以唯一标识元组的属性,数据库中常称为主键,由一个或多个列组成
关系模式:指对关系的描述。其格式为:关系名(属性1,属性2, ... ... ,属性N),在数据库中成为表结构
关系型数据库的优点:
容易理解:二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解
使用方便:通用的SQL语言使得操作关系型数据库非常方便
易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率
关系型数据库瓶颈:
高并发读写需求:硬盘I/O是一个很大的瓶颈
海量数据的高效率读写:在一张包含海量数据的表中查询,效率是非常低的
高扩展性和可用性:在基于web的结构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。对于很多需要提供24小时不间断服务的网站来说,对数据库系统进行升级和扩展是非常痛苦的事情,往往需要停机维护和数据迁移。
对网站来说,关系型数据库的很多特性不再需要了:事务一致性、读写实时性、复杂SQL
关系型数据库在对事物一致性的维护中有很大的开销,而现在很多web2.0系统对事物的读写一致性都不高
对关系数据库来说,插入一条数据之后立刻查询,是肯定可以读出这条数据的,但是对于很多web应用来说,并不要求这么高的实时性.
复杂SQL,特别是多表关联查询不再需要
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,是一项全新的数据库革命性运动。NoSQL数据库的四大分类。
键值(Key-Value)存储数据库:会使用到一个哈希表。
列存储数据库:这部分数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。
文档型数据库:文档型数据库的灵感是来自于Lotus Notes办公软件的,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。如:CouchDB, MongoDb. 国内也有文档型数据库SequoiaDB,已经开源。
图形(Graph)数据库:图形结构的数据库同其他行列以及刚性结构的SQL数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多NoSQL数据库都有REST式的数据接口或者查询API。[2] 如:Neo4J, InfoGrid, Infinite Graph.
因此,我们总结NoSQL数据库在以下的这几种情况下比较适用:1、数据模型比较简单;2、需要灵活性更强的IT系统;3、对数据库性能要求较高;4、不需要高度的数据一致性;5、对于给定key,比较容易映射复杂值的环境。
(简单映射复杂,灵活IT系统,性能要求高一致性要求低)
分类 | Examples举例 | 典型应用场景 | 数据模型 | 优点 | 缺点 |
---|---|---|---|---|---|
键值(key-value)[3] | Tokyo Cabinet/Tyrant, Redis, Voldemort, Oracle BDB | 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。[3] | Key 指向 Value 的键值对,通常用hash table来实现[3] | 查找速度快 | 数据无结构化,通常只被当作字符串或者二进制数据[3] |
列存储数据库[3] | Cassandra, HBase, Riak | 分布式的文件系统 | 以列簇式存储,将同一列数据存在一起 | 查找速度快,可扩展性强,更容易进行分布式扩展 | 功能相对局限 |
文档型数据库[3] | CouchDB, MongoDb | Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) | Key-Value对应的键值对,Value为结构化数据 | 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 | 查询性能不高,而且缺乏统一的查询语法。 |
图形(Graph)数据库[3] | Neo4J, InfoGrid, Infinite Graph | 社交网络,推荐系统等。专注于构建关系图谱 | 图结构 | 利用图结构相关算法。比如最短路径寻址,N度关系查找等 | 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案。[3] |
3. 常用数据库引擎
要利用一种开发工具访问一种数据库,就必须通过一种中介程序,这种开发工具与数据库之间的中介程序就叫数据库引擎。
(1) Mysql数据库引擎
MYSQL支持三个引擎:ISAM、MYISAM和HEAP。另外两种类型INNODB和BERKLEY(BDB),也常常可以使用。
ISAM
在设计之时就考虑到数据库被查询的次数要远大于更新的次数。因此,ISAM执行读取操作的速度很快,而且不占用大量的内存和存储资源。
ISAM的两个主要不足之处在于,它不支持事务处理,也不能够容错:如果你的硬盘崩溃了,那么数据文件就无法恢复了。必须经常备份你所有的实时数据。
MYISAM
MYISAM是MYSQL的ISAM扩展格式和缺省的数据库引擎。除了提供ISAM里所没有的索引和字段管理的大量功能,MYISAM还使用一种表格锁定的机制,来优化多个并发的读写操作。
其代价是你需要经常运行OPTIMIZE TABLE命令,来恢复被更新机制所浪费的空间。
MYISAM还有一些有用的扩展,例如用来修复数据库文件的MYISAMCHK工具和用来恢复浪费空间的MYISAMPACK工具。
MYISAM强调了快速读取操作,这可能就是为什么MYSQL受到了WEB开发如此青睐的主要原因:在WEB开发中你所进行的大量数据操作都是读取操作。所以,大多数虚拟主机提供商和INTERNET平台提供商只允许使用MYISAM格式。
INNODB
包括了对事务处理和外来键的支持,这两点都是前两个引擎所没有的。
(2) Microsoft JET
Access和Visual Basic所提供的内嵌数据库功能的核心元素。JET是一种全能关系数据库引擎,可用来处理多数中小型数据库。(上课常用的)
(3) ODBC
Open DataBase Connectivity(ODBC,开放数据库互连),本质上是一组数据库访问API。(PHP里见过)
它提供一种标准的数据库访问方法以访问不同平台的数据库。一个ODBC应用程序既可以访问在本地PC机上的数据库,也可以访问多种异构平台上的数据库,例如SQL Server、Oracle或者DB2。
4. 事务的隔离级别
(1) 未提交读(read uncommitted):会出现脏读、不可重复读和幻读。脏读的设计只是为了提供非阻塞读,但是对于oracle来说,默认就提供非阻塞读,即查询不会受到任何增删改操作的影像,因为oracle提供了undo来存放更新前的数据。
(2) 提交读(read committed):会出现不可重复读和幻读。oracle的默认事务隔离级别。
(3) 重复读(repeatable read):会出现幻读。
(4) 串行化(serializable):隔离级别最高,不允许出现脏读、不可重复读和幻读。即一个事务执行结束了另一个事务才能执行。当然并发性也就最差。
除了这四种,oracle还提供read only隔离级别,即只支持读,在该级别中,该事务只能看到事务开始那一刻提交的修改。
脏读、不可重复读、幻读含义
脏读:一个事务可以读另一个事务未提交的数据。
不可重复读:在一个事务中不同时间段查询出现不同的结果,可能被更新可能被删除。
幻读:在一个事务中不同时间段查询,记录数不同。与不可重复读的区别是:在幻读中,已经读取的数据不会改变,只是与以前相比,会有更多的数据满足查询条件。
5. 数据库的索引
6. 数据库的优化方式
索引优化
分库分表分区
选择适当的字段类型
读写分离使负载均衡