技术开发 频道

十步优化SQL Server中的数据访问

  第十步:在大表上应用分区

  什么是表分区?

  表分区就是将大表拆分成多个小表,以免检索数据时扫描的数据太多,这个思想参考了“分而治之”的理论。

  当你的数据库中有一个大表(假设有上百万行记录),如果其它优化技巧都用上了,但查询速度仍然非常慢时,你就应该考虑对这个表进行分区了。首先来看一下分区的类型:

  水平分区:假设有一个表包括千万行记录,为了便于理解,假设表有一个自动增长的主键字段(如id),我们可以将表拆分成10个独立的分区表,每个分区包含100万行记录,分区就要依据id字段的值实施,即第一个分区包含id值从1-1000000的记录,第二个分区包含1000001-2000000的记录,以此类推。这种以水平方向分割表的方式就叫做水平分区。

  垂直分区:假设有一个表的列数和行数都非常多,其中某些列被经常访问,其余的列不是经常访问。由于表非常大,所有检索操作都很慢,因此需要基于频繁访问的列进行分区,这样我们可以将这个大表拆分成多个小表,每个小表由大表的一部分列组成,这种垂直拆分表的方法就叫做垂直分区。

  另一个垂直分区的原则是按有索引的列无索引列进行拆分,但这种分区法需要小心,因为如果任何查询都涉及到检索这两个分区,SQL引擎不得不连接这两个分区,那样的话性能反而会低。

  本文主要对水平分区做一介绍。

  分区非常好的实践

  1)将大表分区后,将每个分区放在一个独立的文件中,并将这个文件存放在独立的硬盘上,这样数据库引擎可以同时并行检索多块硬盘上的不同数据文件,提高并发读写速度;

  2)对于历史数据,可以考虑基于历史数据的“年龄”进行分区,例如,假设表中存储的是订单数据,可以使用订单日期列作为分区的依据,如将每年的订单数据做成一个分区。

  如何分区?

  假设Order表中包含了四年(1999-2002)的订单数据,有上百万的记录,那如果要对这个表进行分区,采取的步骤如下:

  1)添加文件组

  使用下面的命令创建一个文件组:

  ALTER DATABASE OrderDB ADD FILEGROUP [1999]

  ALTER DATABASE OrderDB ADD FILE (NAME = N'1999', FILENAME

  = N'C:\OrderDB\1999.ndf', SIZE = 5MB, MAXSIZE = 100MB, FILEGROWTH = 5MB) TO

  FILEGROUP [1999]

  通过上面的语句我们添加了一个文件组1999,然后增加了一个次要数据文件“C:\OrderDB\1999.ndf”到这个文件组中。

  使用上面的命令再创建三个文件组2000,2001和2002,每个文件组存储一年的销售数据。

  2)创建分区函数

  分区函数是定义分界点的一个对象,使用下面的命令创建分区函数:

  CREATE PARTITION FUNCTION FNOrderDateRange (DateTime) AS

  RANGE LEFT FOR VALUES ('19991231', '20001231', '20011231')

  上面的分区函数指定:

  DateTime<=1999/12/31的记录进入第一个分区;

  DateTime > 1999/12/31 且 <= 2000/12/31的记录进入第二个分区;

  DateTime > 2000/12/31 且 <= 2001/12/31的记录进入第三个分区;

  DateTime > 2001/12/31的记录进入第四个分区。

  RANGE LEFT指定应该进入左边分区的边界值,例如小于或等于1999/12/31的值都应该进入第一个分区,下一个值就应该进入第二个分区了。如果使用RANGE RIGHT,边界值以及大于边界值的值都应该进入右边的分区,因此在这个例子中,边界值2000/12/31就应该进入第二个分区,小于这个边界值的值就应该进入第一个分区。

  3)创建分区方案

  通过分区方案在表/索引的分区和存储它们的文件组之间建立映射关系。创建分区方案的命令如下:

  CREATE PARTITION SCHEME OrderDatePScheme AS PARTITION FNOrderDateRange

  TO ([1999], [2000], [2001], [2002])

  在上面的命令中,我们指定了:

  第一个分区应该进入1999文件组;

  第二个分区就进入2000文件组;

  第三个分区进入2001文件组;

  第四个分区进入2002文件组。

  4)在表上应用分区

  至此,我们定义了必要的分区原则,现在需要做的就是给表分区了。首先使用DROP INDEX命令删除表上现有的聚集索引,通常主键上有聚集索引,如果是删除主键上的索引,还可以通过DROP CONSTRAINT删除主键来间接删除主键上的索引,如下面的命令删除PK_Orders主键:

  ALTER TABLE Orders DROP CONSTRAINT PK_Orders;

  在分区方案上重新创建聚集索引,命令如下:

  CREATE UNIQUE CLUSTERED INDEX PK_Orders ON Orders(OrderDate) ON

  OrderDatePScheme (OrderDate)

  假设OrderDate列的数据在表中是唯一的,表将基于分区方案OrderDatePScheme被分区,最终被分成四个小的部分,存放在四个文件组中。如果你对如何分区还有不清楚的地方,建议你去看看微软的官方文章“SQL Server 2005中的分区表和索引”(地址:http://msdn.microsoft.com/en-us/library/ms345146%28SQL.90%29.aspx)。

2
相关文章