1. 分區表簡介數據庫
分區表在邏輯上是一個表,而物理上是多個表。從用戶角度來看,分區表和普通表是同樣的。使用分區表的主要目的是爲改善大型表以及具備多個訪問模式的表的可伸縮性和可管理性。函數
分區表是把數據按設定的標準劃分紅區域存儲在不一樣的文件組中,使用分區能夠快速而有效管理和訪問數據子集。性能
1.1> 適合作分區表的狀況spa
◊ 數據庫中某個表的數據不少,在查詢數據時會明顯感受到速度很慢,這個時候須要考慮分區表;3d
◊ 數據是分段的,如以年份爲分隔的數據,對於當年的數據常常進行增刪改查操做,而對於往年的數據幾乎不作操做或只作查詢操做,這種狀況可使用分區表。對數據的操做若是隻涉及一部分數據而不是所有數據的狀況能夠考慮分區表,若是一張表的數據常用且無論年份之類的因素常常對其增刪改查操做則最好不要分區。code
1.2> 分區表的優勢xml
◊ 分區表能夠從物理上將一個大表分紅幾個小表,可是從邏輯上來看仍是一個大表。blog
◊ 對於具備多個CPU的系統,分區能夠對錶的操做經過並行的方式進行,能夠提高訪問性能。排序
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')
查看添加分區後的數據物理存儲: