數據庫分區表(一)什么情況下需要分區,准備需要分區的數據
什么數據庫需要進行分區?首先看一下我們的案例:2010年6月我們六期IT開發團隊接到一個XX全國連鎖店的餐飲系統,經過一周的敏捷開發之后,XX餐飲系統正式上線了,由於該軟件的功能強大,操作簡單,功能靈活等特性,很快在全國各地鋪展開來。XX餐飲店的美食也頗受顧客的喜愛,有的店每天的收入高達1W元人民幣,每天這么多的收入,那么每天要產生多大的訂單呢?< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />
這是一個很大的數據量,在剛開始的幾個月中,我們還能夠正常根據所產生的所有訂單,根據產品的類別和銷售情況,產生一個商品銷售排行報表。可是隨着數據量越來越大,現在每次進行商品銷售排行匯總都要進行很長時間的等待。而我們的服務器性能是沒有問題的,那么我們只有改善數據庫的結構來提高數據的檢索效率了。改善數據庫的結構有兩種,一種是采用存儲過程代替普通的SQL語句,另外一種就是使用數據庫系統中增強索引和規划分區表進行優化,這里我們采用第二種方案來解決問題。
我們這里采用數據分區表的方法來進行數據優化,那么是不是只要數據量足夠大之后就要進行數據庫分區表來提高查詢效率呢?數據多了並不是創建分區表的惟一條件,哪怕你有一千萬條記錄,但是這一千萬條記錄都是常用的記錄,那么最好也不要使用分區表,說不定會得不償失。只有你的數據是分段的數據,那么才要考慮到是否需要使用分區表。這里我們的數據是按時間段進行查詢的,所以我們可以在這里進行分區。
上面這些就是我們進行數據分區表的前提,如果你有這樣的需求,那么還等什么,趕快使用數據分區表吧。這里我們提供一個簡單的數據庫,方便以后實例的練習,如果你需要的話,可以點擊這里下載。如果你有一個剛剛備份過來的數據庫,就是還原不成功怎么辦?這里有解決方案。
數據庫分區表(二)什么是分區表?
表分區分為水平分區和垂直分區。水平分區將表分為多個表。每個表包含的列數相同,但是行更少。例如,可以將一個包含十億行的表水平分區成 12 個表,每個小表表示特定年份內一個月或幾個月的數據。任何需要特定月份數據的查詢只需引用相應月份的表。而垂直分區則是將原始表分成多個只包含較少列的表。水平分區是最常用分區方式,后面我們以水平分區來介紹具體實現方法。
簡單一點說,分區表就是將一個大表分成若干個小表。這里,我們有一個銷售記錄表,記錄着每個某餐飲店的訂單情況,那么你就可以把這個銷售記錄表按時間分成幾個小表,我們這里分成15個小表。2011年以前的記錄使用一個表,2011年的記錄每兩個月使用一個表(2011//01/01-2011/03/01,每個兩個月一個表,一共六個表),2012年,2013()年的的記錄同上,2013年的記錄使用一個表,2012年以后的記錄使用一個表。那么,你想查詢哪個年份的記錄,就可以去相對應的表里查詢,由於每個表中的記錄數少了,查詢起來時間自然也會減少。
但將一個大表分成幾個小表的處理方式,會給程序員增加編程上的難度。以添加記錄為例,以上15個表是獨立的15個表,在不同時間添加記錄的時候,程序員要使用不同的SQL語句,例如在2011年添加記錄時,程序員要將記錄添加到2011年那個表里;在2012年添加記錄時,程序員要將記錄添加到2012年的那個表里。這樣,程序員的工作量會增加,出錯的可能性也會增加。
使用分區表就可以很好的解決以上問題。分區表可以從物理上將一個大表分成幾個小表,但是從邏輯上來看,還是一個大表。分區表可以將一個銷售記錄表分成十五個物理上的小表,但是對於程序員而言,他所面對的依然是一個大表,無論是2010年添加記錄還是2012年添加記錄,對於程序員而言是不需要考慮的,他只要將記錄插入到銷售記錄表——這個邏輯中的大表里就行了。SQL Server會自動地將它放在它應該呆在的那個物理上的小表里。
同樣,對於查詢而言,程序員也只需要設置好查詢條件,OK,SQL Server會自動將去相應的表里查詢,不用管太多事了。
分區表的准備工作完事了,下一步就是具體創建分區表了,等不急了吧,看下篇博文你就知道了。
數據庫分區表(三)如何創建分區表1?
創建分區表必須要經過下面五個步驟。
1)創建文件組
2)創建文件
3)創建分區函數
4)創建分區方案
5)創建分區表
(1)創建文件組,有兩種方案,一種是通過手動添加,另外一種就是通過SQL腳本進行添加。下面以兩種方案來說明:
方案一:創建文件組,雖然這一步我們可以省略,因為我們可以直接使用Primary文件(也就是系統主文件)。但是為了方便管理,我們還是要創建幾個文件組,這樣可以將不同的小表(不同時間段,或者不同數據表)放在不同的文件組里,既便於理解又可以提高運行速度。
打開SQL Server Management Studio,找到分區表所在的數據庫,右鍵單擊選擇“屬性”,選擇“文件組”選項,單擊下面的“添加”按鈕,添加X個文件組,如下圖所示:

方案二:通過查詢分析器SQL腳本執行
ALTER DATABASE CXFunSche ADD FILEGROUP CXFG2010
ALTER DATABASE CXFunSche ADD FILEGROUP CXFG2011
ALTER DATABASE CXFunSche ADD FILEGROUP CXFG2012
ALTER DATABASE CXFunSche ADD FILEGROUP CXFG2013
(2)創建數據庫文件
方案一:創建了文件組之后,還要再創建幾個數據庫文件。為什么要創建數據庫文件,這很好理解,因為分區的小表必須要放在硬盤上,而放在硬盤上的什么地方呢?當然是文件里啦。再說了,文件組中沒有文件,文件組還要來有啥用呢?還是在上圖的那個界面,選擇“文件”選項,然后添加幾個文件。在添加文件的時候要注意以下幾點:
1、不要忘記將不同的文件放在文件組中。當然一個文件組中也可以包含多個不同的文件。
2、如果可以的話,將不同的文件放在不同的硬盤分區里,最好是放在不同的獨立硬盤里。要知道IQ的速度往往是影響SQL Server運行速度的重要條件之一。將不同的文件放在不同的硬盤上,可以加快SQL Server的運行速度。
在本文的實例中,數據庫主文件與分區文件就不在同一個目錄下,各個分區文件也可以放置在不同的目錄下,建議大家在練習時使用。

方案二:通過查詢分析器SQL腳本執行
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail2010', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail2010.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2010
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail201102', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail201102.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2010
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail201104', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail201104.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2011
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail201106', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail201106.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2011
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail201108', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail201108.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2011
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail201110', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail201110.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2011
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail201112', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail201112.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2011
ALTER DATABASE CXFunSche ADD FILE ( NAME = N'SellLogDetail201202', FILENAME = N'D:\program files\Programming Software\SQL Server 2005\MSSQL.1\MSSQL\DATA\SellLogDetail201202.ndf' , SIZE = 3072KB , FILEGROWTH = 1024KB ) TO FILEGROUP CXFG2012
.
.
.
由於創建的數據文件太多了,這里就不一一貼出來了,剩下的幾個,留給大家自己鍛煉一下吧。創建完分區文件后,你就可以在D盤相應的目錄下找到你剛剛創建的數據文件。
數據庫分區表(三)如何創建分區表2?
(3)創建分區函數
創建一個分區函數,創建分區函數的目的是告訴SQL Server以什么方式對分區表進行分區。這一步必須要什么SQL腳本來完成。以上面的例子,我們要將銷售記錄表按時間分成15個小表。划分的時間為:
第1個小表:2011-01-01以前的數據(不包含2010-01-01)。
第2個小表:2011-01-01(包含2011-01-01)到2010-01-01之間的數據。
第3個小表:2011-03-01(包含2011-03-01)到2011-05-01之間的數據。
第4個小表:2011-05-01(包含2011-05-01)到2011-07-01之間的數據。
第5個小表:……
第6個小表:……
--創建分區函數
CREATE PARTITION FUNCTION partfun_CX (datetime)
AS RANGE RIGHT FOR VALUES('20110101','20110301','20110501','20110701','20110901','20111101','20120101','20120301','20120501','20120701','20120901','20121101','20130101','20130301','20130501','20130701')
1、CREATE PARTITION FUNCTION意思是創建一個分區函數。
2、partfun_CX為分區函數名稱。
3、AS RANGE RIGHT為設置分區范圍的方式為Right,也就是右置方式。
4、FOR VALUES ('20110101','20110301','20110501','20130101',……)為按這些個值來分區,Values中的值就是分區的條件
(4)創建分區方案
分區方案的作用是將分區函數生成的分區映射到文件組中去。分區函數的作用是告訴SQL Server,如何將數據進行分區,而分區方案的作用則是告訴SQL Server將已分區的數據放在哪個文件組中。
--.創建分區方案
CREATE PARTITION SCHEME partsch_CX
AS PARTITION partfun_CX
TO (
CX2010,
CX2011, CX2011, CX2011, CX2011, CX2011,CX2011,
CX2012, CX2012, CX2012, CX2012, CX2012,CX2012,
CX2013, CX2013, CX2013, CX2013)
1、CREATE PARTITION SCHEME意思是創建一個分區方案。
2、partsch_CX為分區方案名稱。
3、AS PARTITION partfun_CX說明該分區方案所使用的數據划分條件(也就是所使用的分區函數)為partfun_CX。
4、TO后面的內容是指partfun_CX分區函數划分出來的數據對應存放的文件組。
到此為止,分區函數和分區方案就創建完畢了。創建后的分區函數和分區方案在數據庫的“存儲”中可以看到
(5)創建分區表
創建分區表,創建方式和創建普遍表類似,如下所示:
CREATE TABLE t_partition3(
ptId int IDENTITY(1,1) NOT NULL primary key NONCLUSTERED,
ptName varchar(16) NOT NULL,
sellTime[datetime] NOT NULL
) ON partsch_CX(sellTime)
如果你按照上面的代碼來實現的話出出現下圖所示的錯誤代碼提示:
消息1908,級別16,狀態1,第1 行
列'sellTime' 是索引'PK__t_partition3__671F4F74' 的分區依據列。唯一索引的分區依據列必須是索引鍵的子集。
消息1750,級別16,狀態0,第1 行
無法創建約束。請參閱前面的錯誤消息。
這里是不能創建除分區表中除分區字段以外的其它字段為聚集索引,因為聚集索引是在物理上順序存儲的,而分區表是將數據分別存儲在不同的表中,這兩個概念是沖突的。如果我們創建了其它字段的聚集索引,那么就會按照其它字段在物理上順序存儲,而我們的分區表是根據分區字段進行物理上的順序存儲的。
數據庫分區表(四)將普通表轉換成分區表
2011-02-15 16:27:43| 分類: 數據庫學習 | 標簽: |字號大中小 訂閱
我們的數據庫已經投入使用一段時間了,但是當時沒有創建創建分區表,現在我們需要做的是將普通表轉換成分區表,但是並不能影響我們數據庫里面的數據,那么我們應該如何做呢?只需在該表上創建一個聚集索引,並在該聚集索引中使用分區方案即可。
說的很簡單,但是在實現實現可就沒有那么容易了,因為你的數據庫中存在主鍵,外鍵等約束關系,那么我們在將普通表轉換成分區表時,首先就需要解決這些問題。
我們知道分區表時某個字段為分區條件的,除了這個字段之外的其他字段是不能創建聚集索引的,所以我們將普通表轉換成分區表時,必須要刪除聚集索引,然后再重新創建一個新的聚集索引,在該聚集索引中使用分區方案。
但是我們需要修改的t_sellLog表中的orderId既是主鍵又是聚集索引,而且還是其它表的外鍵。因此,我們只能先刪除外鍵關聯,再刪除主鍵,然后重新創建orderId為主鍵,但是設置為非聚集索引,然后將我們的sellTime字段設置為聚集索引,最后添加上我們的外鍵約束,至此普通表轉換成分區表的工作結束,代碼如下:
--查看外鍵約束
use CX_Partiton_Scheme
exec sp_helpconstraint t_SellLog
--刪除外鍵約束
alter table t_sellLog drop constraint FK_t_SellLog_t_User
--刪掉主鍵
ALTER TABLE t_SellLog DROP constraint PK_t_SellLog
--創建主鍵,但不設為聚集索引
ALTER TABLE t_SellLog ADD CONSTRAINT PK_t_SellLog PRIMARY KEY NONCLUSTERED (
orderId ASC
)
ON [PRIMARY]
--創建一個新的聚集索引,在該聚集索引中使用分區方案
CREATE CLUSTERED INDEX CT_SellLog ON t_SellLog(sellTime)
ON partsch_CX([sellTime])
--添加刪除掉的外鍵約束(具體自己根據實際情況自己實現)
轉換成功之后,我們可以通過下面代碼查看每個分區表中的記錄數:
--統計所有分區表中的記錄總數
select $PARTITION.partfun_CX([sellTime]) as 分區編號,count(orderId) as 記錄數from t_SellLog group by$PARTITION.partfun_CX([sellTime])
我們還可以通過下面的代碼,查看數據庫庫中的數據在哪個分區中:
--查看數據庫表中的數據在哪個分區中
select $PARTITION.partfun_CX('2010-10-1') --查詢年月日的數據在哪個分區中
select $PARTITION.partfun_CX('2011-01-1') --查詢年月日的數據在哪個分區中如果你想比較一下我們使用分區方案之后和之前程序有多少效率提高,我們可以通過下面的語句來看看一下腳本的執行時間就OK了,我經過測試的數據是快了0.017秒,一方面由於我們的測試數據量比較小,另一方面我的機器配置還是蠻不錯的。
--查看SQL腳本的執行時間
select getDate()
select * from t_sellLog
select getDate()