物理结构的设计,也即是设计数据在磁盘上的存储,需要考虑:安全(容灾)、性能(IO竞争少)、服务器资源利用率高。

通常当前数据库只使用一份ONLINE的数据源,至于分布式存储已经上升到服务器架构的设计,这里不作讨论。以下仅简单描述非分布式存储的情况,主要从磁盘、文件、表数据三方面来说。

一、磁盘

RAID0提供了最好的读写性能,但RAID0没有提供冗余恢复策略,所以很少单独全用。通常,使用RAID10或RAID5来实现磁盘数据的存储与容灾。

随着磁盘上数据量的提升,RAID5的读写性能会明显低于RAID10,RAID5至少需要3块磁盘,RAID10至少需要4块磁盘,RAID5在同样提供数据容灾的情况下,更能节省成本,但如果成本不在考虑范围内,当然是性能优先,使用RAID10。

二、文件

2.1、文件组(表空间)

在SQL SERVER中叫文件组,在ORACLE中叫表空间,它们都是对数据文件的逻辑分组。使用文件组的目的如下:

(1)性能

文件组中的文件放在不同磁盘上,是否可以提高读写的效率?在使用RAID1或RAID5的情况下,这种效率的提升已经几乎可以忽略,因为数据本身已经被分散写到RAID上的各块磁盘上;

(2)管理

目前使用文件组的目的,大都出于管理。
a)在磁盘空间不足的情况下,可以使用多个小空间的磁盘,同时,也可为数据库扩展新的磁盘空间;
b)文件组的备份/还原,只读/读写,离线/在线等数据库管理与维护;

SQL SERVER中文件组与文件的关系如下图:

物理结构设计mysql 物理结构设计要点_数据

2.2、文件

(1)如果文件组中的文件被限制大小,文件填满了会不会自动新建一个文件?
不会,那么此时数据库会报出空间不足的错误,所以在定义文件时,要么指定其大小无限增长(直到填满磁盘空间),要么定期检查文件空闲空间的大小,以手动扩展。

(2)文件组中文件是一个个写入还是各个文件同时都在增大?
SQL SERVER中是文件组中各个文件同时写入,ORACLE中是写满一个再写下一个。

三、表数据

3.1、堆表和索引组织表

使用堆表还是索引组织表,取决于对DML效率的要求。
(1)堆表在DML时没有聚集索引的维护成本,在非明确指定的情况下,ORACLE中默认使用堆表;
(2)对于主键的单值或范围查找,尤其是范围查找,索引组织表效率更高,因为省去了bookmark lookup的成本,在非明确指定的情况下,SQL SERVER中默认使用索引组织表。

关于堆表和索引组织表的设计,详见《SQL Server 查询优化》系列。

3.2、表数据分割

数据分割的方式,通常可分为以下两种:

3.2.1、水平分割

出于读写性能的考虑,将一个大表,拆分为若干个小的单元,应用程序根据每个单元的入口规则,映射到相应的单元,只处理所需访问的单元中的数据,以提高数据读写的效率。

水平分割针对表中数据行进行分割,可采用以下方式:

(1)分表

在还没出现分区的概念时,对于大表,通常采用分表的方式来实现数据的水平分割。

按照一定的规则将数据分别存入不同名称的表中:
a)最常见的就是按日期、时间来分表,比如:将每月的订单放到当前月的订单表中,orders_201001、orders_201002、orders_201003……依次类推;

b)也可以根据编号规则来分表,比如将尾数:将订单尾数为1的订单放到一个表中,orders_1、orders_2、orders_3……依次类推;

(2)表分区

a)SQL SERVER 2005以前的版本中,出现过分区视图,算是它在分区表出现前的一个替代品,有本地分区视图和分布式分区视图两种。分布式分区视图的概念,倒是有现在分布式存储的味道,但由于受网络因素影响较大,未被广泛使用。

b)对于本地化的表分区,目前多采用分区表,结构如下图:

物理结构设计mysql 物理结构设计要点_物理结构设计mysql_02

3.2.2、垂直分割

垂直分割针对表中列进行分割。
如果表中列非常多,从而导致一行数据所占用的存储空间非常大时,可以考虑进行垂直分割,比如:将一个表拆成主表和从表,主表中存放访问最频繁的列,从表中存放访问较少的列,从而提高数据读取的效率。

通常不建议使用垂直分区,如果主从表都变得很大,在需要进行主从表关联时,成本也是相当高的,可能会影响性能。

3.3、簇

簇(CLUSTER),这是ORACLE里的一个概念,将多个表中相同的字段存放到一起,称为簇,即聚集的意思,这里需要和聚集索引的概念区分开来。放到一起的好处如下:
(1)节省存储空间,相同数据只需要存一份;
(2)提高多表关联的速度;