|
執(zhí)行SQL查詢時(shí),主要的幾個(gè)瓶頸在于:CPU運(yùn)算速度、內(nèi)存緩存區(qū)大小、磁盤(pán)IO速度。而對(duì)于大數(shù)據(jù)量數(shù)據(jù)的查詢,其瓶頸則一般集中于磁盤(pán)IO,以及內(nèi)存緩存。那么為了提高SQL查詢的效率,一方面我們需要考慮盡量減少查詢?cè)O(shè)計(jì)的數(shù)據(jù)條目數(shù)——建立索引,設(shè)立分區(qū);另一方面,我們也可以考慮切實(shí)減少數(shù)據(jù)表物理大小,從而減少I(mǎi)O大小。
在SQL Server 2008中,最新提供了一項(xiàng)功能“壓縮(Compression)”,就是定位于減少數(shù)據(jù)表、索引物理大小。
設(shè)置壓縮
在企業(yè)管理器中,在需要壓縮的表或索引上右鍵選擇Storage-》Manage Compression:
這里可以看到幾點(diǎn):
- 下方列表里列出了該表所有的分區(qū),也就是可以同一張表的不同分區(qū)應(yīng)用不同的壓縮策略。
- 壓縮方式(Compression Type)分為Row和Page兩種。
行級(jí)壓縮(Row):
一方面減少了動(dòng)態(tài)長(zhǎng)度字段元數(shù)據(jù)的大小(varchar、varbinary等),比如之前存儲(chǔ)字段實(shí)際長(zhǎng)度需要2bytes,壓縮后只需要3bits。
另一方面也直接減少各字段存儲(chǔ)內(nèi)容的大小,比如存儲(chǔ)數(shù)值1在一個(gè)int類型字段中,壓縮后只占用了一個(gè)字節(jié)。
頁(yè)級(jí)壓縮(Page):能在各行間共享相同的數(shù)據(jù),這里面包含兩項(xiàng)技術(shù):列前綴(Column Prefix)、頁(yè)字典(Page Dictionary)。
列前綴可以讓擁有同樣前綴的字段值擁有類似外鍵一樣的結(jié)構(gòu)來(lái)存儲(chǔ)相同的前綴和各自的其余部分。比如一張存儲(chǔ)了一個(gè)網(wǎng)站所有頁(yè)面URL的表,URL字段存儲(chǔ)的值分別是‘www.example.com/a.html’,‘www.example.com/b.html’,‘www.example.com/c.html’,‘www.example.com/d.html’。則壓縮后,它們同樣的前綴‘www.example.com/’會(huì)被提取出來(lái),而其余部分會(huì)被類似如下的形式存儲(chǔ)‘1a.html’,‘1b.html’,‘1c.html’,‘1d.html’。
頁(yè)字典則可以將在應(yīng)用列前綴基礎(chǔ)上的其余部分再次聚合存儲(chǔ),比如同樣是一張存儲(chǔ)了一個(gè)網(wǎng)站所有頁(yè)面URL的表,假設(shè)有在表里里有多條URL字段的值相同,比如‘1a.html’,‘1b.html’,‘1c.html’,‘1b.html’,‘1a.html’,‘1a.html’,則通過(guò)頁(yè)字典技術(shù)壓縮后,實(shí)際存儲(chǔ)在字段中的值會(huì)進(jìn)一步減少為‘2’,‘3’,‘1c.html’(沒(méi)有重復(fù)的字段值不會(huì)被壓縮),‘3’,‘2’,‘2’。 - 點(diǎn)擊“Calculate”后,會(huì)計(jì)算出表當(dāng)前占用的空間大小,以及壓縮需要的空間大小。注意這里與一般預(yù)想的不同,如果要對(duì)一張預(yù)存有數(shù)據(jù)但尚未壓縮的表進(jìn)行壓縮,首先需要的是額外的空間大小。
執(zhí)行壓縮
設(shè)置好之后,就可以選擇是生成腳本還是立即執(zhí)行,一般壓縮的執(zhí)行時(shí)間受表原有數(shù)據(jù)多少以及選擇壓縮方式的影響。筆者對(duì)一張有上千萬(wàn)條記錄的表做頁(yè)級(jí)壓縮,耗時(shí)在10分鐘左右。
壓縮完成之后查看數(shù)據(jù)庫(kù)大小,會(huì)發(fā)現(xiàn)數(shù)據(jù)庫(kù)的大小變大了!這也和在設(shè)置階段計(jì)算出來(lái)的額外空間相關(guān)。但實(shí)際上這里大部分空間是預(yù)占的空間,并沒(méi)有實(shí)際數(shù)據(jù)。如果需要節(jié)省磁盤(pán)空間,需要進(jìn)一步執(zhí)行收縮(Shrink)操作。
與Compression不同,Shrink用來(lái)釋放數(shù)據(jù)庫(kù)占據(jù)的沒(méi)有利用的空間,一般用來(lái)對(duì)無(wú)用的日志文件收縮(如果操作頻繁,日志文件很有可能大于數(shù)據(jù)庫(kù)實(shí)際數(shù)據(jù)的大小)。這里我們對(duì)數(shù)據(jù)庫(kù)文件(mdf)做Shrink操作,完成之后再看數(shù)據(jù)庫(kù)的大小,果然減少了很多。筆者做壓縮、Shrink之后,一般都能將數(shù)據(jù)庫(kù)的大小減為原來(lái)的1/3~1/2左右。當(dāng)然,具體壓縮比率取決于壓縮方式、壓縮表的字段特點(diǎn)、壓縮表占整個(gè)數(shù)據(jù)庫(kù)數(shù)據(jù)的比重等。
注意事項(xiàng)
- 既然對(duì)表行了壓縮,那么在執(zhí)行查詢時(shí)必然會(huì)有解壓縮的過(guò)程。而這一過(guò)程會(huì)占用CPU時(shí)間,也就是我們?cè)谕ㄟ^(guò)壓縮減少了磁盤(pán)占用空間以及IO時(shí)間的同時(shí),增大了CPU的消耗。所以在壓縮前需要考慮清楚查詢的瓶頸到底是磁盤(pán)IO還是內(nèi)存還是CPU。而且如果表應(yīng)用了壓縮,類似建立索引,對(duì)于增刪改等操作也會(huì)有一定的影響。所以同樣要考慮應(yīng)用在表上的操作到底以哪種為主。
- 各頁(yè)面的壓縮是獨(dú)立進(jìn)行的,頁(yè)字典和列前綴也分別存儲(chǔ)于各頁(yè)內(nèi)。而且壓縮僅在數(shù)據(jù)頁(yè)快滿的時(shí)候進(jìn)行,因?yàn)橐粋€(gè)頁(yè)的大小是固定的,壓縮半頁(yè)不會(huì)有性能上的提升。
- 數(shù)據(jù)庫(kù)備份中也有Compression的選項(xiàng),但這利用的是系統(tǒng)的文件壓縮技術(shù),而且只能應(yīng)用于整個(gè)數(shù)據(jù)庫(kù)上。
- 容易被忽略的是,索引也能被壓縮,而且和表壓縮獨(dú)立,同樣也會(huì)提升所有應(yīng)用到索引的查詢的性能。
- 在Shrink階段,可能會(huì)造成大量的索引碎片,所以可以在Shrink完成之后重建或者重組織索引,但同時(shí),這些操作也會(huì)造成數(shù)據(jù)庫(kù)的體積變大……也就是,最小的數(shù)據(jù)庫(kù)體積和最小碎片比率的索引是魚(yú)與熊掌,不可兼得。
it知識(shí)庫(kù):【原】SqlServer性能優(yōu)化——Compression,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。