如果你有一張表,表內(nèi)有1億條數(shù)據(jù),查詢和更新都會(huì)很慢。對(duì)于這種情況,主要原因是出在了IO上。單單靠加索引是不行了。所以得另想辦法。
下面的分析比較貼近實(shí)際,
如果一年前的只是備份待查,分離出來(lái)另存.如果一年前的會(huì)用到,但用得少,用分區(qū).如果一年前的仍然要頻繁使用,用分區(qū),但要加一個(gè)磁盤.
那么就討論一下分區(qū)吧,
下面的內(nèi)容來(lái)自這個(gè)博客
http://www.cnblogs.com/CareySon/category/
和這個(gè)博客
http://www.cnblogs.com/sienpower/archive/2011/12/31/2308741.html
簡(jiǎn)介分區(qū)表是在SQL SERVER2005之后的版本引入的特性。這個(gè)特性允許把邏輯上的一個(gè)表在物理上分為很多部分。而對(duì)于SQL SERVER2005之前版本,所謂的分區(qū)表僅僅是分布式視圖,也就是多個(gè)表做union操作.
分區(qū)表在邏輯上是一個(gè)表,而物理上是多個(gè)表.這意味著從用戶的角度來(lái)看,分區(qū)表和普通表是一樣的。這個(gè)概念可以簡(jiǎn)單如下圖所示:
而對(duì)于SQL SERVER2005之前的版本,是沒(méi)有分區(qū)這個(gè)概念的,所謂的分區(qū)僅僅是分布式視圖:
本篇文章所講述的分區(qū)表指的是SQL SERVER2005之后引入的分區(qū)表特性.
為什么要對(duì)表進(jìn)行分區(qū)在回答標(biāo)題的問(wèn)題之前,需要說(shuō)明的是,表分區(qū)這個(gè)特性只有在企業(yè)版或者開(kāi)發(fā)版中才有,還有理解表分區(qū)的概念還需要理解SQL SERVER中文件和文件組的概念.
*文件,文件組
http://www.cnblogs.com/CareySon/archive/2011/12/26/2301597.html
對(duì)表進(jìn)行分區(qū)在多種場(chǎng)景下都需要被用到.通常來(lái)說(shuō),使用表分區(qū)最主要是用于:
分區(qū)表的定義大體上分為三個(gè)步驟:
分區(qū)函數(shù),分區(qū)構(gòu)架和分區(qū)表的關(guān)系如下:
分區(qū)表依賴分區(qū)構(gòu)架,而分區(qū)構(gòu)架又依賴分區(qū)函數(shù).值得注意的是,分區(qū)函數(shù)并不屬于具體的分區(qū)構(gòu)架和分區(qū)表,他們之間的關(guān)系僅僅是使用關(guān)系.
下面我們通過(guò)一個(gè)例子來(lái)看如何定義一個(gè)分區(qū)表:
假設(shè)我們需要定義的分區(qū)表結(jié)構(gòu)如下:
第一列為自增列,orderid為訂單id列,SalesDate為訂單日期列,也就是我們需要分區(qū)的依據(jù).
下面我們按照上面所說(shuō)的三個(gè)步驟來(lái)實(shí)現(xiàn)分區(qū)表.
定義分區(qū)函數(shù)分區(qū)函數(shù)是用于判定數(shù)據(jù)行該屬于哪個(gè)分區(qū),通過(guò)分區(qū)函數(shù)中設(shè)置邊界值來(lái)使得根據(jù)行中特定列的值來(lái)確定其分區(qū),上面例子中,我們可以通過(guò)SalesDate的值來(lái)判定其不同的分區(qū).假設(shè)我們想定義兩個(gè)邊界值(boundaryValue)進(jìn)行分區(qū),則會(huì)生成三個(gè)分區(qū),這里我設(shè)置邊界值分別為2004-01-01和2007-01-01,則前面例子中的表會(huì)根據(jù)這兩個(gè)邊界值分成三個(gè)區(qū):
在MSDN中,定義分區(qū)函數(shù)的原型如下:
CREATE PARTITION FUNCTION partition_function_name ( input_parameter_type )AS RANGE [ LEFT | RIGHT ] FOR VALUES ( [ boundary_value [ ,...n ] ] ) [ ; ]
通過(guò)定義分區(qū)函數(shù)的原型,我們看出其中并沒(méi)有具體涉及具體的表.因?yàn)榉謪^(qū)函數(shù)并不和具體的表相綁定.上面原型中還可以看到Range left和right.這個(gè)參數(shù)是決定臨界值本身應(yīng)該歸于“left”還是“right”:
下面我們根據(jù)上面的參數(shù)定義分區(qū)函數(shù):
通過(guò)系統(tǒng)視圖,可以看見(jiàn)這個(gè)分區(qū)函數(shù)已經(jīng)創(chuàng)建成功
定義分區(qū)構(gòu)架定義完分區(qū)函數(shù)僅僅是知道了如何將列的值區(qū)分到了不同的分區(qū)。而每個(gè)分區(qū)的存儲(chǔ)方式,則需要分區(qū)構(gòu)架來(lái)定義.使用分區(qū)構(gòu)架需要你對(duì)文件和文件組有點(diǎn)了解.
我們先來(lái)看MSDN的分區(qū)構(gòu)架的原型:
CREATE PARTITION SCHEME partition_scheme_nameAS PARTITION partition_function_name[ ALL ] TO ( { file_group_name | [ PRIMARY ] } [ ,...n ] )[ ; ]
從原型來(lái)看,分區(qū)構(gòu)架僅僅是依賴分區(qū)函數(shù).分區(qū)構(gòu)架中負(fù)責(zé)分配每個(gè)區(qū)屬于哪個(gè)文件組,而分區(qū)函數(shù)是決定如何在邏輯上分區(qū):
基于之前創(chuàng)建的分區(qū)函數(shù),創(chuàng)建分區(qū)構(gòu)架:
接下來(lái)就該創(chuàng)建分區(qū)表了.表在創(chuàng)建的時(shí)候就已經(jīng)決定是否是分區(qū)表了。雖然在很多情況下都是你在發(fā)現(xiàn)已經(jīng)表已經(jīng)足夠大的時(shí)候才想到要把表分區(qū),但是分區(qū)表只能夠在創(chuàng)建的時(shí)候指定為分區(qū)表。
為剛建立的分區(qū)表PartitionedTable加入5萬(wàn)條測(cè)試數(shù)據(jù),其中SalesDate隨機(jī)生成,從2001年到2010年隨機(jī)分布.加入數(shù)據(jù)后,我們通過(guò)如下語(yǔ)句來(lái)看結(jié)果:
select convert(varchar(50), ps.name) as partition_scheme,p.partition_number, convert(varchar(10), ds2.name) as filegroup, convert(varchar(19), isnull(v.value, ''), 120) as range_boundary, str(p.rows, 9) as rowsfrom sys.indexes i join sys.partition_schemes ps on i.data_space_id = ps.data_space_id join sys.destination_data_spaces ddson ps.data_space_id = dds.partition_scheme_id join sys.data_spaces ds2 on dds.data_space_id = ds2.data_space_id join sys.partitions p on dds.destination_id = p.partition_numberand p.object_id = i.object_id and p.index_id = i.index_id join sys.partition_functions pf on ps.function_id = pf.function_id LEFT JOIN sys.Partition_Range_values v on pf.function_id = v.function_idand v.boundary_id = p.partition_number - pf.boundary_value_on_right WHERE i.object_id = object_id('PartitionedTable')and i.index_id in (0, 1) order by p.partition_number
可以看到我們分區(qū)的數(shù)據(jù)分布:
分區(qū)表的分割。相當(dāng)于新建一個(gè)分區(qū),將原有的分區(qū)需要分割的內(nèi)容插入新的分區(qū),然后刪除老的分區(qū)的內(nèi)容,概念如下圖:
假設(shè)我新加入一個(gè)分割點(diǎn):2009-01-01,則概念如下:
通過(guò)上圖我們可以看出,如果分割時(shí),被分割的分區(qū)3內(nèi)有內(nèi)容需要分割到分區(qū)4,則這些數(shù)據(jù)需要被復(fù)制到分區(qū)4,并刪除分區(qū)3上對(duì)應(yīng)數(shù)據(jù)。
這種操作非常非常消耗IO,并且在分割的過(guò)程中鎖定分區(qū)三內(nèi)的內(nèi)容,造成分區(qū)三的內(nèi)容不可用。不僅僅如此,這個(gè)操作生成的日志內(nèi)容會(huì)是被轉(zhuǎn)移數(shù)據(jù)的4倍!
所以我們?nèi)绻幌胍驗(yàn)檫@種操作給客戶帶來(lái)麻煩而被老板爆菊的話…最好還是把分割點(diǎn)建立在未來(lái)(也就是預(yù)先建立分割點(diǎn)),比如2012-01-01。則分區(qū)3內(nèi)的內(nèi)容不受任何影響。在以后2012的數(shù)據(jù)加入時(shí),自動(dòng)插入到分區(qū)4.
分割現(xiàn)有的分區(qū)需要兩個(gè)步驟:
1.首先告訴SQL SERVER新建立的分區(qū)放到哪個(gè)文件組
2.建立新的分割點(diǎn)
可以通過(guò)如下語(yǔ)句來(lái)完成:
如果我們的分割構(gòu)架在定義的時(shí)候已經(jīng)指定了NEXT USED,則直接添加分割點(diǎn)即可。
通過(guò)文中前面查看分區(qū)的長(zhǎng)語(yǔ)句..再來(lái)看:
新的分區(qū)已經(jīng)加入!
分區(qū)的合并分區(qū)的合并可以看作分區(qū)分割的逆操作。分區(qū)的合并需要提供分割點(diǎn),這個(gè)分割點(diǎn)必須在現(xiàn)有的分割表中已經(jīng)存在,否則進(jìn)行合并就會(huì)報(bào)錯(cuò)
假設(shè)我們需要根據(jù)2009-01-01來(lái)合并分區(qū),概念如下:
只需要使用merge參數(shù):
再來(lái)看分區(qū)信息:
這里值得注意的是,假設(shè)分區(qū)3和分區(qū)4不再一個(gè)文件組,則合并后應(yīng)該存在哪個(gè)文件組呢?換句話說(shuō),是由分區(qū)3合并到分區(qū)4還是由分區(qū)4合并到分區(qū)3?這個(gè)需要看我們的分區(qū)函數(shù)定義的是left還是right.如果定義的是left.則由左邊的分區(qū)3合并到右邊的分區(qū)4.反之,則由分區(qū)4合并到分區(qū)3:
本文從講解了SQL SERVER中分區(qū)表的使用方式。分區(qū)表是一個(gè)非常強(qiáng)大的功能。使用分區(qū)表相對(duì)傳統(tǒng)的分區(qū)視圖來(lái)說(shuō),對(duì)于減少DBA的管理工作來(lái)說(shuō),會(huì)更勝一籌!
新聞熱點(diǎn)
疑難解答
圖片精選