什麼數據庫須要進行分區?首先看一下咱們的案例:2010年6月咱們六期IT開發團隊接到一個XX全國連鎖店的餐飲系統,通過一週的敏捷開發以後,XX餐飲系統正式上線了,因爲該軟件的功能強大,操做簡單,功能靈活等特性,很快在全國各地鋪展開來。XX餐飲店的美食也頗受顧客的喜好,有的店天天的收入高達1W元人民幣,天天這麼多的收入,那麼天天要產生多大的訂單呢?< xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" />mysql
這是一個很大的數據量,在剛開始的幾個月中,咱們還可以正常根據所產生的全部訂單,根據產品的類別和銷售狀況,產生一個商品銷售排行報表。但是隨着數據量愈來愈大,如今每次進行商品銷售排行彙總都要進行很長時間的等待。而咱們的服務器性能是沒有問題的,那麼咱們只有改善數據庫的結構來提升數據的檢索效率了。改善數據庫的結構有兩種,一種是採用存儲過程代替普通的SQL語句,另一種就是使用數據庫系統中加強索引和規劃分區表進行優化,這裏咱們採用第二種方案來解決問題。程序員
咱們這裏採用數據分區表的方法來進行數據優化,那麼是否是隻要數據量足夠大以後就要進行數據庫分區表來提升查詢效率呢?數據多了並非建立分區表的唯一條件,哪怕你有一千萬條記錄,可是這一千萬條記錄都是經常使用的記錄,那麼最好也不要使用分區表,說不定會得不償失。只有你的數據是分段的數據,那麼纔要考慮到是否須要使用分區表。這裏咱們的數據是按時間段進行查詢的,因此咱們能夠在這裏進行分區。sql
上面這些就是咱們進行數據分區表的前提,若是你有這樣的需求,那麼還等什麼,趕快使用數據分區表吧。這裏咱們提供一個簡單的數據庫,方便之後實例的練習,若是你須要的話,能夠點擊這裏下載。若是你有一個剛剛備份過來的數據庫,就是還原不成功怎麼辦?這裏有解決方案。數據庫
表分區分爲水平分區和垂直分區。水平分區將表分爲多個表。每一個表包含的列數相同,可是行更少。例如,能夠將一個包含十億行的表水平分區成 12 個表,每一個小表表示特定年分內一個月或幾個月的數據。任何須要特定月份數據的查詢只需引用相應月份的表。而垂直分區則是將原始表分紅多個只包含較少列的表。水平分區是最經常使用分區方式,後面咱們以水平分區來介紹具體實現方法。編程
簡單一點說,分區表就是將一個大表分紅若干個小表。這裏,咱們有一個銷售記錄表,記錄着每一個某餐飲店的訂單狀況,那麼你就能夠把這個銷售記錄表按時間分紅幾個小表,咱們這裏分紅15個小表。2011年之前的記錄使用一個表,2011年的記錄每兩個月使用一個表(2011//01/01-2011/03/01,每一個兩個月一個表,一共六個表),2012年,2013()年的的記錄同上,2013年的記錄使用一個表,2012年之後的記錄使用一個表。那麼,你想查詢哪一個年份的記錄,就能夠去相對應的表裏查詢,因爲每一個表中的記錄數少了,查詢起來時間天然也會減小。服務器
但將一個大表分紅幾個小表的處理方式,會給程序員增長編程上的難度。以添加記錄爲例,以上15個表是獨立的15個表,在不一樣時間添加記錄的時候,程序員要使用不一樣的SQL語句,例如在2011年添加記錄時,程序員要將記錄添加到2011年那個表裏;在2012年添加記錄時,程序員要將記錄添加到2012年的那個表裏。這樣,程序員的工做量會增長,出錯的可能性也會增長。 ide
使用分區表就能夠很好的解決以上問題。分區表能夠從物理上將一個大表分紅幾個小表,可是從邏輯上來看,仍是一個大表。分區表能夠將一個銷售記錄表分紅十五個物理上的小表,可是對於程序員而言,他所面對的依然是一個大表,不管是2010年添加記錄仍是2012年添加記錄,對於程序員而言是不須要考慮的,他只要將記錄插入到銷售記錄表——這個邏輯中的大表裏就好了。SQL Server會自動地將它放在它應該呆在的那個物理上的小表裏。函數
一樣,對於查詢而言,程序員也只須要設置好查詢條件,OK,SQL Server會自動將去相應的表裏查詢,不用管太多事了。性能
分區表的準備工做完事了,下一步就是具體建立分區表了,等不急了吧,看下篇博文你就知道了。學習
建立分區表必需要通過下面五個步驟。
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)建立數據庫文件
方案一:建立了文件組以後,還要再建立幾個數據庫文件。爲何要建立數據庫文件,這很好理解,由於分區的小表必需要放在硬盤上,而放在硬盤上的什麼地方呢?固然是文件裏啦。再說了,文件組中沒有文件,文件組還要來有啥用呢?仍是在上圖的那個界面,選擇「文件」選項,而後添加幾個文件。在添加文件的時候要注意如下幾點:
一、不要忘記將不一樣的文件放在文件組中。固然一個文件組中也能夠包含多個不一樣的文件。
二、若是能夠的話,將不一樣的文件放在不一樣的硬盤分區裏,最好是放在不一樣的獨立硬盤裏。要知道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盤相應的目錄下找到你剛剛建立的數據文件。
(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')
一、CREATE PARTITION FUNCTION意思是建立一個分區函數。
二、partfun_CX爲分區函數名稱。
三、AS RANGE RIGHT爲設置分區範圍的方式爲Right,也就是右置方式。
四、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)
一、CREATE PARTITION SCHEME意思是建立一個分區方案。
二、partsch_CX爲分區方案名稱。
三、AS PARTITION partfun_CX說明該分區方案所使用的數據劃分條件(也就是所使用的分區函數)爲partfun_CX。
四、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()