(转)SQLServer分区表操做

           原文地址:https://www.cnblogs.com/libingql/p/4087598.htmlhtml

1. 分区表简介数据库

  分区表在逻辑上是一个表,而物理上是多个表。从用户角度来看,分区表和普通表是同样的。使用分区表的主要目的是为改善大型表以及具备多个访问模式的表的可伸缩性和可管理性。函数

  分区表是把数据按设定的标准划分红区域存储在不一样的文件组中,使用分区能够快速而有效管理和访问数据子集。性能

1.1> 适合作分区表的状况.net

  ◊ 数据库中某个表的数据不少,在查询数据时会明显感受到速度很慢,这个时候须要考虑分区表;3d

  ◊ 数据是分段的,如以年份为分隔的数据,对于当年的数据常常进行增删改查操做,而对于往年的数据几乎不作操做或只作查询操做,这种状况可使用分区表。对数据的操做若是只涉及一部分数据而不是所有数据的状况能够考虑分区表,若是一张表的数据常用且无论年份之类的因素常常对其增删改查操做则最好不要分区。code

1.2> 分区表的优势xml

  ◊ 分区表能够从物理上将一个大表分红几个小表,可是从逻辑上来看仍是一个大表。htm

  ◊ 对于具备多个CPU的系统,分区能够对表的操做经过并行的方式进行,能够提高访问性能。blog

2. 建立分区表步骤

  建立分区表的步骤分为5步:

  (1)建立数据库文件组

  (2)建立数据库文件

  (3)建立分区函数

  (4)建立分区方案

  (5)建立分区表

2.1> 建立数据库文件组

  新建示例数据库Northwind,建立数据库文件组和文件,添加文件组。

  

2.2> 建立数据库文件

  建立数据文件,并为数据文件分配文件组。

  

  完成建立后的数据库文件信息

  

  经过SQL Server Profiler能够看到具体的建立数据库的脚本以下:

CREATE DATABASE [Northwind]
 CONTAINMENT = NONE
 ON  PRIMARY 
( NAME = N'Northwind', FILENAME = N'F:\Database\Northwind\Northwind.mdf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), 
 FILEGROUP [SECTION2010] 
( NAME = N'Northwind_Data_2010', FILENAME = N'F:\Database\Northwind\Northwind_Data_2010.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), 
 FILEGROUP [SECTION2011] 
( NAME = N'Northwind_Data_2011', FILENAME = N'F:\Database\Northwind\Northwind_Data_2011.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), 
 FILEGROUP [SECTION2012] 
( NAME = N'Northwind_Data_2012', FILENAME = N'F:\Database\Northwind\Northwind_Data_2012.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), 
 FILEGROUP [SECTION2013] 
( NAME = N'Northwind_Data_2013', FILENAME = N'F:\Database\Northwind\Northwind_Data_2013.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB ), 
 FILEGROUP [SECTION2014] 
( NAME = N'Northwind_Data_2014', FILENAME = N'F:\Database\Northwind\Northwind_Data_2014.ndf' , SIZE = 5120KB , FILEGROWTH = 1024KB )
 LOG ON 
( NAME = N'Northwind_log', FILENAME = N'F:\Database\Northwind\Northwind_log.ldf' , SIZE = 2048KB , FILEGROWTH = 10%)

  查看数据库文件组SQL语句:

2.3> 建立分区函数

  建立分区函数Transact-SQL语法:

CREATE PARTITION FUNCTION partition_function_name ( input_parameter_type )
AS RANGE [ LEFT | RIGHT ] 
FOR VALUES ( [ boundary_value [ ,...n ] ] ) 
[ ; ]

  参数:  

  partition_function_name:分区函数的名称。 分区函数名称在数据库内必须惟一,而且符合标识符的规则。

  input_parameter_type:用于分区的列的数据类型。 当用做分区列时,除 text、ntext、image、xml、timestamp、varchar(max)、nvarchar(max)、varbinary(max)、别名数据类型或 CLR 用户定义数据类型外,全部数据类型均有效。

  boundary_value:为使用 partition_function_name 的已分区表或索引的每一个分区指定边界值。 若是 boundary_value 为空,则分区函数使 partition_function_name 将整个表或索引映射到单个分区。 只能使用 CREATE TABLE 或 CREATE INDEX 语句中指定的一个分区列。

  LEFT | RIGHT 指定当间隔值由 数据库引擎 按升序从左到右排序时,boundary_value [ ,...n ] 属于每一个边界值间隔的哪一侧(左侧仍是右侧)。 若是未指定,则默认值为 LEFT。

  示例:建立将用于Order表的分区函数

CREATE PARTITION FUNCTION Function_DateTime ( DATETIME )
AS RANGE RIGHT
FOR VALUES('2011-01-01', '2012-01-01', '2013-01-01', '2014-01-01')

  完成建立分区函数以后,能够经过如下SQL语句查看已建立的分区函数状况。

SELECT * FROM sys.partition_functions

2.4> 建立分区方案

  分区方案的做用是将分区函数生成的分区映射到文件组中去,分区方案是让SQL Server将已分区的数据放在哪一个文件组中。

  在当前数据库中建立一个将已分区表或已分区索引的分区映射到文件组的方案。 已分区表或已分区索引的分区的个数和域在分区函数中肯定。 必须首先在 CREATE PARTITION FUNCTION 语句中建立分区函数,而后才能建立分区方案。

  建立分区方案的Transact-SQL语法:

CREATE PARTITION SCHEME partition_scheme_name
AS PARTITION partition_function_name
[ ALL ] TO ( { file_group_name | [ PRIMARY ] } [ ,...n ] )
[ ; ]

  参数:

  partition_scheme_name:分区方案的名称。 分区方案名称在数据库中必须是惟一的,而且符合标识符规则。

  partition_function_name:使用分区方案的分区函数的名称。 分区函数所建立的分区将映射到在分区方案中指定的文件组。 partition_function_name 必须已经存在于数据库中。 单个分区不能同时包含 FILESTREAM 和非 FILESTREAM 文件组。

  ALL:指定全部分区都映射到在 file_group_name 中提供的文件组,或映射到主文件组(若是指定了 [PRIMARY]。 若是指定了 ALL,则只能指定一个 file_group_name。

  file_group_name | [ PRIMARY ] [ ,...n]:指定用来持有由 partition_function_name 指定的分区的文件组的名称。 file_group_name 必须已经存在于数据库中。
  若是指定了 [PRIMARY],则分区将存储于主文件组中。 若是指定了 ALL,则只能指定一个 file_group_name。 分区分配到文件组的顺序是从分区 1 开始,按文件组在 [,...n] 中列出的顺序进行分配。 在 [,...n] 中,能够屡次指定同一个 file_group_name。 若是 n 不足以拥有在 partition_function_name 中指定的分区数,则 CREATE PARTITION SCHEME 将失败,并返回错误。
  若是 partition_function_name 生成的分区数少于文件组数,则第一个未分配的文件组将标记为 NEXT USED,而且出现显示命名 NEXT USED 文件组的信息。 若是指定了 ALL,则单独的 file_group_name 将为该 partition_function_name 保持它的 NEXT USED 属性。 若是在 ALTER PARTITION FUNCTION 语句中建立了一个分区,则 NEXT USED 文件组将再接收一个分区。 若要再建立一个未分配的文件组来拥有新的分区,请使用 ALTER PARTITION SCHEME。
  在 file_group_name[ 1,...n] 中指定主文件组时,必须像在 [PRIMARY] 中那样分隔 PRIMARY,由于它是关键字。

 

  示例:建立将用于Order表的分区方案

CREATE PARTITION SCHEME Scheme_DateTime
AS PARTITION Function_DateTime
TO ( SECTION2010, SECTION2011, SECTION2012, SECTION2013, SECTION2014 )

  分区函数和分区方案建立以后,能够在数据库的【存储】中查看:

  经过能够经过如下SQL语句查看已建立的分区方案:

SELECT * FROM sys.partition_schemes

2.5> 建立分区表

CREATE TABLE [Order]
(
    OrderID INT IDENTITY(1,1) NOT NULL,
    UserID INT NOT NULL,
    TotalAmount DECIMAL(18,2) NULL,
    OrderDate DATETIME NOT NULL
) ON Scheme_DateTime ( OrderDate )

  这里须要注意分区表不能再建立汇集索引,由于汇集索引能够将记录在物理上顺序存储,而分区表是将数据存储在不一样的表中,这两个概念是冲突的,因此在建立分区表时不能再建立汇集索引。

  完成Order表建立以后,查看表的属性,能够看到Order表已是分区表。

3. 操做分区表

3.1> Insert数据

USE [Northwind]
GO

INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (1 ,10.00 ,'2009-10-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (1 ,20.50 ,'2009-12-31');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (2 ,40.00 ,'2010-01-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (3 ,40.00 ,'2010-10-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (4 ,50.00 ,'2011-10-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (5 ,60.00 ,'2012-10-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (5 ,60.00 ,'2012-10-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (6 ,70.00 ,'2013-10-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (10 ,90.00 ,'2014-10-20');
INSERT INTO [dbo].[Order] ([UserID],[TotalAmount] ,[OrderDate]) VALUES (9 ,100.00 ,'2015-10-20');
GO

3.2> 查询数据所在物理分区表

  在分区表中使用通常的SELECT语句没法知道数据是分别存放在哪几个不一样的物理表中,若要知道数据分别存放的物理表,可使用$PARTITION函数,该函数能够调用分区函数并返回数据所在物理分区的编号。

  $PARTITION的语法:$PARTITION.分区函数名(表达式)

SELECT $PARTITION.Function_DateTime('2010-01-01')

  查询结果分区函数返回为1,说明2010-01-01的数据会存放在第1个物理分区表中。

  使用$PARTITION函数能够具体知道每一个物理分区表中存放了哪些记录。

  查看物理分区表中存放的记录:

SELECT * FROM [Order] WHERE $PARTITION.Function_DateTime(OrderDate) = 1

SELECT $PARTITION.Function_DateTime(OrderDate) AS 分区编号, COUNT(1) AS 记录数 
FROM [Order]
GROUP BY $PARTITION.Function_DateTime(OrderDate)

3.3> 修改分区表数据

UPDATE dbo.[Order] SET OrderDate='2015-01-01' WHERE OrderID = 3

4. 将普通表转换为分区表

  通常的普通表都是在主键上建汇集索引,记录的物理保存位置由主键决定。

  示例:建立一个Product普通表

CREATE TABLE Product
(
    ProductID INT IDENTITY(1,1) NOT NULL,
    ProductName VARCHAR(100) NOT NULL,
    UnitPrice DECIMAL(18,2) NULL,
    CreateDate DATETIME NOT NULL,
    CONSTRAINT PK_Product PRIMARY KEY CLUSTERED (ProductID)
)
USE [Northwind]
GO

INSERT INTO [dbo].[Product] ([ProductName],[UnitPrice],[CreateDate]) VALUES ('LINQ to SQL' ,10 ,'2012-01-01');
INSERT INTO [dbo].[Product] ([ProductName],[UnitPrice],[CreateDate]) VALUES ('LINQ to XML' ,10 ,'2012-12-01');
INSERT INTO [dbo].[Product] ([ProductName],[UnitPrice],[CreateDate]) VALUES ('LINQ to Object' ,10 ,'2013-02-01');
INSERT INTO [dbo].[Product] ([ProductName],[UnitPrice],[CreateDate]) VALUES ('LINQ to ADO.NET' ,10 ,'2014-01-02');
INSERT INTO [dbo].[Product] ([ProductName],[UnitPrice],[CreateDate]) VALUES ('LINQ to Entity' ,10 ,'2015-01-01');

GO

  查看表Product的属性:

  查看表Product的索引,能够看到PK_Product为汇集索引。

  将普通表转换为分区表的操做是先在普通表上删除汇集索引,在建立一个新的汇集索引,在该汇集索引中使用分区方案。

  在SQL Server中,主键字段上默认建立汇集索引,删除主键的汇集索引。

ALTER TABLE Product DROP CONSTRAINT PK_Product

  从新建立主键非汇集索引

ALTER TABLE Product ADD CONSTRAINT PK_Product PRIMARY KEY NONCLUSTERED (ProductID ASC)

  从新建立后的主键:

  建立使用分区方案的汇集索引:

CREATE CLUSTERED INDEX IX_CreateDate ON Product ( CreateDate )
ON Scheme_DateTime ( CreateDate )

  调整后的Product表属性:

  调整后Product表记录的物理保存状况:

5. 删除(合并)一个分区表

  删除2012-01-01的分区,修改分区函数:

ALTER PARTITION FUNCTION Function_DateTime() MERGE RANGE ('2012-01-01')

  在修改了分区函数以后,与之关联的分区方案也将同时自动调整。在执行了上面合并分区的函数以后,查看分区方案的Create脚本。

CREATE PARTITION SCHEME [Scheme_DateTime] AS PARTITION [Function_DateTime] TO ([SECTION2010], [SECTION2011], [SECTION2013], [SECTION2014])

  合并分区以后,被合并的分区记录也将被从新分配物理保存位置。

6. 添加分区

  分区方案中指定的文件组个数比分区函数中指定的边界数大1,为分区方案指定一个可用的文件组时,该分区方案并无马上使用这个文件组,只是将文件组先备用着,等修改了分区函数以后分区方案才会使用这个文件组。若是分区函数没有更改,分区方案中的文件组个数也不会更改。

   添加分区所须要使用到的文件组可使用以前合并分区以后没有再使用的SECTION2012,也能够新建文件组。

ALTER DATABASE [Northwind] ADD FILEGROUP [SECTION2015]
ALTER DATABASE [Northwind] ADD FILE 
( 
    NAME = N'Northwind_Data_2015', 
    FILENAME = N'F:\Database\Northwind\Northwind_Data_2015.ndf' , 
    SIZE = 5120KB , 
    FILEGROWTH = 1024KB 
) TO FILEGROUP [SECTION2015]

  为分区方案指定一个可用的文件组:

ALTER PARTITION SCHEME Scheme_DateTime NEXT USED [SECTION2015]

  修改分区函数,添加分区:

ALTER PARTITION FUNCTION Function_DateTime() SPLIT RANGE('2015-01-01')

  查看添加分区后的数据物理存储:

 

参考文章

1)https://blog.csdn.net/smallfools/article/details/4930810  什么是分区表,如何建立

2)https://blog.csdn.net/smallfools/article/details/4932936如何添加、查询、修改分区表

3)https://blog.csdn.net/smallfools/article/details/4934119 将普通表转为分区表

4)https://blog.csdn.net/smallfools/article/details/4937878 删除合并一个分区

5)https://blog.csdn.net/smallfools/article/details/4940185 添加一个分区

6)https://blog.csdn.net/smallfools/article/details/5004100 分区表转成普通表

7)https://www.cnblogs.com/ljhdo/p/5667328.html 数据库文件操做

8)https://www.cnblogs.com/CareySon/p/3252670.html

相关文章
相关标签/搜索