深入淺出SQL Server 2008 分區函數和分區表

深入淺出SQL Server 2008 分區函數和分區表

當我們數據量比較大的時候,我們需要將大型表拆分爲多個較小的表,則只訪問部門數據的查詢就可以更快的運行,基本原理就是,因爲要掃描的數據變的更小。維護任務(例如,重新生成索引或備份表)也可以更快的運行。

   我們可以再不通過將表物理放置在多個磁盤驅動器上來拆分表的情況下獲取分區。如果將某個表放置在一個物理驅動器上,將相關表放置在另一個驅動器上,則可以提高查詢性能,因爲當運行涉及表間連接的查詢時,多個磁盤頭同時讀取數據。可以使用SQL Server文件組來指定放置表的磁盤。

  對於分區的方式,基本就三種方式:硬件分區、水平分區、垂直分區。相關方案可以參考SQL聯機叢書

  這裏我們介紹分區表的具體實戰方法:

  第一步,首先建立我們要使用的數據庫,最重要的是建立多個文件組。

  我們先新建立四個目錄,來組成文件組,一個用來存放主文件的目錄:Primary

  三個數據文件目錄:FG1、FG2、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
複製代碼

第二步:建立分區函數,目的是用來規範不同數據存放到不同目錄的標準,簡單講就是如何分區。

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,未來某年)

第三步:創建分區方案,關聯到分區函數。目的就是我們將已經建立好的分區函數組織成一套方案,簡單點將就是我們在哪裏對數據進行分區。

Use Sales
go
create  partition  scheme ps_OrderDate
as 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表我們還沒有歸檔數據,所以爲空。

我們來分條件查詢下:

1、查詢某個分區

這裏我們要用到$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屬於哪個分區,代碼如下:

 2、歸檔數據

假如現在是2003年年初,那麼我們就可以把2002您所有的交易記錄歸檔到我們剛纔建立的歷史訂單表HistroryOrder中。代碼如下:

Use Sales
go
alter table orders switch partition 1 to ordersHistory partition 1
go

現在我們再重新查看這兩張表的數據:

這時候Orders表只剩下2003年的數據,而OdersHistory表中包含了2002年的數據。

簡單點講就是把第一區的數據導入到另一張分區表的第一區中

當然如果到了2004年年初,我們就可以歸檔2003年的所有交易數據。

Use Sales
go
alter table orders switch partition 2 to ordersHistory partition 2
go

這裏需要注意的是我們按照區進行數據修改的時候,必須是同一種分區函數下的分區表進行操作,並且分區結構相對應,如果不這樣會報錯,例如:

  3、添加分區

當我們需要新添加分區的時候,我們需要修改分區方案,比如現在我們到了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,未來某年)

4、刪除分區

刪除分區又稱合併分區,簡單講就是兩個分區的數據進行合併,比如我們想合併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分區的數據了。
5、查看元數據

我們可以通過三個系統視圖來查看我們的分區函數,分區方案,邊界值點等。

select * from sys.partition_functions   
select * from sys.partition_range_values
select * from sys.partition_schemes
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章