當咱們數據量比較大的時候,咱們須要將大型表拆分爲多個較小的表,則只訪問部門數據的查詢就能夠更快的運行,基本原理就是,由於要掃描的數據變的更小。維護任務(例如,從新生成索引或備份表)也能夠更快的運行。sql
咱們能夠再不經過將表物理放置在多個磁盤驅動器上來拆分表的狀況下獲取分區。若是將某個表放置在一個物理驅動器上,將相關表放置在另外一個驅動器上,則能夠提升查詢性能,由於當運行涉及表間鏈接的查詢時,多個磁盤頭同時讀取數據。可使用SQL Server文件組來指定放置表的磁盤。數據庫
對於分區的方式,基本就三種方式:硬件分區、水平分區、垂直分區。相關方案能夠參考SQL聯機叢書express
這裏咱們介紹分區表的具體實戰方法:數組
第一步,首先創建咱們要使用的數據庫,最重要的是創建多個文件組。ide
咱們先新創建四個目錄,來組成文件組,一個用來存放主文件的目錄:Primary函數
三個數據文件目錄:FG一、FG二、FG3性能
創建庫: 測試
create database Sales on primary ( name=N'Sales', filename=N'G:\data\Primary\Sales.mdf', size=3MB, maxsize=100MB, filegrowth=10% ), filegroup FG1 ( NAME = N'File1', FILENAME = N'G:\data\FG1\File1.ndf', SIZE = 1MB, MAXSIZE = 100MB, FILEGROWTH = 10% ), FILEGROUP FG2 ( NAME = N'File2', FILENAME = N'G:\data\FG2\File2.ndf', SIZE = 1MB, MAXSIZE = 100MB, FILEGROWTH = 10% ), FILEGROUP FG3 ( NAME = N'File3', FILENAME = N'G:\data\FG3\File3.ndf', SIZE = 1MB, MAXSIZE = 100MB, FILEGROWTH = 10% ) LOG ON ( NAME = N'Sales_Log', FILENAME = N'G:\data\Primary\Sales_Log.ldf', SIZE = 1MB, MAXSIZE = 100MB, FILEGROWTH = 10% ) GO
第二步:創建分區函數,目的是用來規範不一樣數據存放到不一樣目錄的標準,簡單講就是如何分區。spa
USE Sales GO CREATE PARTITION FUNCTION pf_OrderDate (datetime) AS RANGE RIGHT FOR VALUES ('2003/01/01', '2004/01/01') GO
咱們建立了一個用於數據類型爲datetime的分區函數,按照時間段來劃分
文件組 分區 取值範圍
FG1 1 (過去某年, 2003/01/01)
FG2 2 [2003/01/01, 2004/01/01)
FG3 3 [2004/01/01,將來某年)code
第三步:建立分區方案,關聯到分區函數。目的就是咱們將已經創建好的分區函數組織成一套方案,簡單點將就是咱們在哪裏對數據進行分區。
Use Sales go create partition scheme ps_OrderDateas partition pf_OrderDate to(FG2,FG2,FG3) go
很簡單,就是將第二步創建的分區函數應用已經創建的分區組中。
第四步:建立分區表。建立表並將其綁定到分區方案上。咱們首先創建兩個表,一張原始表另外一張用來歸檔數據,保存歸檔數據。
Use Sales go create table Orders ( OrderID int identity(10000,1), OrderDate datetime not null, CustomerID int not null, constraint PK_Orders primary key(OrderID,OrderDate) ) on ps_OrderDate(OrderDate) go create table OrdersHistory ( OrderID int identity(10000,1), OrderDate datetime not null, CustomerID int not null, constraint PK_OrdersHistory primary key(OrderID,OrderDate) ) on ps_OrderDate(OrderDate) go
到這裏,經過上面的四步咱們已經完整的搭建好了一個帶有分區表的庫,咱們來插入一些數據,來測試下咱們創建是否好用。
首先,由於是用2003年1月1號做爲區分點的,咱們先向數據表中寫入2002年的規範數據
USE Sales GO INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2002/6/25', 1000) INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2002/8/13', 1000) INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2002/8/25', 1000) INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2002/9/23', 1000) GO
一樣咱們寫入2003年四條數據
USE Sales GO INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2003/6/25', 1000) INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2003/8/13', 1000) INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2003/8/25', 1000) INSERT INTO dbo.Orders (OrderDate, CustomerID) VALUES ('2003/9/23', 1000) GO
咱們來查看這些數據是否完整錄入:
由於OrdersHistory表咱們尚未歸檔數據,因此爲空。
咱們來分條件查詢下:
一、查詢某個分區
這裏咱們要用到$partition函數。這個函數在聯機叢書中是這樣解釋的:
用法: 爲任何指定的分區函數返回分區號,一組分區列值將映射到該分區號中。 語法: [ database_name. ] $PARTITION.partition_function_name(expression) 參數: database_name 包含分區函數的數據庫的名稱。 partition_function_name 對其應用一組分區列值的任何現有分區函數的名稱。 expression 其數據類型必須匹配或可隱式轉換爲其對應分區列數據類型的表達式。expression 也能夠是當前參與 partition_function_name 的分區列的名稱。 返回類型:int 備註: $PARTITION 返回從 1 到分區函數的分區數之間的 int 值。 $PARTITION 將針對任何有效值返回分區號,不管此值當前是否存在於使用分區函數的分區表或索引中。
咱們來查詢分區表Order的第一個分區,代碼以下:
能夠看到咱們查詢出來的數據所有爲2002年的,也就是說在第一分區中咱們存入的數據都是小於2003年,按照此推斷2003年的數據,就應該存在第二分區中:
結果如咱們所料,咱們能夠按照這個分區進行分組來查看各個分區的數據行多少,代碼以下:
select $partition.pf_OrderDate(OrderDate) as Patition,COUNT(*) countRow from dbo.Orders group by $partition.pf_OrderDate(OrderDate)
還能夠經過$Partition函數得到一組分區標識列值的分區號,例如得到2002屬於哪一個分區,代碼以下:
二、歸檔數據
假如如今是2003年年初,那麼咱們就能夠把2002您全部的交易記錄歸檔到咱們剛纔創建的歷史訂單表HistroryOrder中。代碼以下:
Use Sales go alter table orders switch partition 1 to ordersHistory partition 1go
如今咱們再從新查看這兩張表的數據:
這時候Orders表只剩下2003年的數據,而OdersHistory表中包含了2002年的數據。
簡單點講就是把第一區的數據導入到另外一張分區表的第一區中
固然若是到了2004年年初,咱們就能夠歸檔2003年的全部交易數據。
Use Sales go alter table orders switch partition 2 to ordersHistory partition 2 go
這裏須要注意的是咱們按照區進行數據修改的時候,必須是同一種分區函數下的分區表進行操做,而且分區結構相對應,若是不這樣會報錯,例如:
三、添加分區
當咱們須要新添加分區的時候,咱們須要修改分區方案,好比如今咱們到了2005年年初,咱們須要爲2005年的交易記錄準備分區,就須要添加分區:
USE [master] GO ALTER DATABASE [Sales] ADD FILEGROUP [FG4] GO ALTER DATABASE [Sales] ADD FILE ( NAME = N'File4', FILENAME = N'G:\data\FG4\File4.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP [FG4] GO
咱們新創建了一個文件組,然咱們一樣按照上面的方法,進行修改分區函數和方案:
use Sales go alter partition scheme ps_OrderDate next used [FG4] alter partition function pf_OrderDate() split range('2005/01/01') go
咱們這裏用alter partition Scheme ps_OrderDate Next Used FG4用來指定新分區的數據在那個文件。這裏Next Used FG4指定的就是咱們剛纔新創建的第四個文件組。固然咱們能夠放在原來已經創建的文件組,爲了防治數據混亂存放咱們大部分是新創建文件組。
alter partition function pf_OrderDate() split range('2005/01/01')表明我麼建立一個新分區,而這裏split range是建立新分區的關鍵語法。
至此,咱們就有了四個分區,此時的區間以下:
文件組 分區 取值範圍
FG1 1 (過去某年, 2003/01/01)
FG2 2 [2003/01/01, 2004/01/01)
FG3 3 [2004/01/01,2005/01/01]
FG4 4 [2004/01/01,將來某年)
四、刪除分區
刪除分區又稱合併分區,簡單講就是兩個分區的數據進行合併,好比咱們想合併2002年的分區和2003年的分區到一個分區,咱們能夠用以下的代碼:
use Sales go alter partition function pf_OrderDate() merge range('2003/01/01') go
也就是將2003年這個分區點去掉,裏面分區裏面的數據會自動合併到一塊兒。
執行完上面的代碼,此時分區區間以下:
文件組 分區 取值範圍
Fg2 1 [過去某年, 2004/01/01)
Fg3 2 [2004/01/01, 2005/01/01)
Fg2 3 [2005/01/01, 將來某年)
合併2002和2003年的數據到2003年以後,咱們執行以下代碼:
SELECT Sales.$PARTITION.pf_OrderDate('2003')
你會發現返回的結果是1。而原來返回的是2,緣由是2002年之前數據所在的那個分區合併到了2003年這個分區中了。
此時咱們執行下面代碼:
SELECT *FROM dbo.OrdersHistory WHERE $PARTITION.pf_OrderDate(OrderDate) = 2
結果一行數據都沒返回,事實就這樣,由於OrderHistroy表中只存儲了2002和2003年的歷史數據,在沒有合併分區以前,執行上面的代碼確定會查詢出2003年的數據,可是合併了分區以後,上面代碼實際查詢的是第二個分區中2004年的數據。
不過咱們改爲以下代碼:
SELECT *FROM dbo.OrdersHistory WHERE $PARTITION.pf_OrderDate(OrderDate) = 1
便會查詢出8行數據,包括2002年和2003年的數據,由於合併分區後2002年和2003年的數據都成了第1分區的數據了。
五、查看元數據
咱們能夠經過三個系統視圖來查看咱們的分區函數,分區方案,邊界值點等。
select * from sys.partition_functions select * from sys.partition_range_valuesselect * from sys.partition_schemes