sql索引碎片產(chǎn)生的原理 解決碎片的辦法

本文講述了SQL SERVER中碎片產(chǎn)生的原理,內(nèi)部碎片和外部碎片的概念克婶。以及解決碎片的辦法和填充因子.在數(shù)據(jù)庫(kù)中,往往每一個(gè)對(duì)于某一方面性能增加的功能也會(huì)伴隨著另一方面性能的減弱。系統(tǒng)的學(xué)習(xí)數(shù)據(jù)庫(kù)知識(shí)磨取,從而根據(jù)具體情況進(jìn)行權(quán)衡,是dba和開發(fā)人員的必修課

本文需要你對(duì)索引和SQL中數(shù)據(jù)的存儲(chǔ)方式有一定了解

在SQL Server中柴墩,存儲(chǔ)數(shù)據(jù)的最小單位是頁(yè)忙厌,每一頁(yè)所能容納的數(shù)據(jù)為8060字節(jié).而頁(yè)的組織方式是通過(guò)B樹結(jié)構(gòu)(表上沒(méi)有聚集索引則為堆結(jié)構(gòu),不在本文討論之列)如下圖:

image-20210720092628204.png

在聚集索引B樹中江咳,只有葉子節(jié)點(diǎn)實(shí)際存儲(chǔ)數(shù)據(jù)逢净,而其他根節(jié)點(diǎn)和中間節(jié)點(diǎn)僅僅用于存放查找葉子節(jié)點(diǎn)的數(shù)據(jù).

每一個(gè)葉子節(jié)點(diǎn)為一頁(yè),每頁(yè)是不可分割的. 而SQL Server向每個(gè)頁(yè)內(nèi)存儲(chǔ)數(shù)據(jù)的最小單位是表的行(Row).當(dāng)葉子節(jié)點(diǎn)中新插入的行或更新的行使得葉子節(jié)點(diǎn)無(wú)法容納當(dāng)前更新或者插入的行時(shí)歼指,分頁(yè)就產(chǎn)生了.在分頁(yè)的過(guò)程中爹土,就會(huì)產(chǎn)生碎片.

理解外部碎片

首先,理解外部碎片的這個(gè)“外”是相對(duì)頁(yè)面來(lái)說(shuō)的东臀。外部碎片指的是由于分頁(yè)而產(chǎn)生的碎片.比如着饥,我想在現(xiàn)有的聚集索引中插入一行,這行正好導(dǎo)致現(xiàn)有的頁(yè)空間無(wú)法滿足容納新的行惰赋。從而導(dǎo)致了分頁(yè):

image-20210720092651188.png

因?yàn)樵赟QL SERVER中宰掉,新的頁(yè)是隨著數(shù)據(jù)的增長(zhǎng)不斷產(chǎn)生的,而聚集索引要求行之間連續(xù)赁濒,所以很多情況下分頁(yè)后和原來(lái)的頁(yè)在磁盤上并不連續(xù).

這就是所謂的外部碎片.

由于分頁(yè)會(huì)導(dǎo)致數(shù)據(jù)在頁(yè)之間的移動(dòng)轨奄,所以如果插入更新等操作經(jīng)常需要導(dǎo)致分頁(yè),則會(huì)大大提升IO消耗拒炎,造成性能下降.

而對(duì)于查找來(lái)說(shuō)挪拟,在有特定搜索條件,比如where子句有很細(xì)的限制或者返回?zé)o序結(jié)果集時(shí)击你,外部碎片并不會(huì)對(duì)性能產(chǎn)生影響玉组。但如果要返回掃描聚集索引而查找連續(xù)頁(yè)面時(shí),外部碎片就會(huì)產(chǎn)生性能上的影響.

在SQL Server中谎柄,比頁(yè)更大的單位是區(qū)(Extent).一個(gè)區(qū)可以容納8個(gè)頁(yè).區(qū)作為磁盤分配的物理單元.所以當(dāng)頁(yè)分割如果跨區(qū)后,需要多次切區(qū)惯雳。需要更多的掃描.因?yàn)樽x取連續(xù)數(shù)據(jù)時(shí)會(huì)不能預(yù)讀朝巫,從而造成額外的物理讀,增加磁盤IO.

理解內(nèi)部碎片

和外部碎片一樣石景,內(nèi)部碎片的”內(nèi)”也是相對(duì)頁(yè)來(lái)說(shuō)的.下面我們來(lái)看一個(gè)例子:

image-20210720092716045.png

我們創(chuàng)建一個(gè)表劈猿,這個(gè)表每個(gè)行由int(4字節(jié)),char(999字節(jié))和varchar(0字節(jié)組成),所以每行為1003個(gè)字節(jié),則8行占用空間1003*8=8024字節(jié)加上一些內(nèi)部開銷潮孽,可以容納在一個(gè)頁(yè)面中:


image-20210720092741420.png

當(dāng)我們隨意更新某行中的col3字段后揪荣,造成頁(yè)內(nèi)無(wú)法容納下新的數(shù)據(jù),從而造成分頁(yè):

image-20210720092758742.png

分頁(yè)后的示意圖:

image-20210720092807974.png

而當(dāng)分頁(yè)時(shí)如果新的頁(yè)和當(dāng)前頁(yè)物理上不連續(xù)往史,則還會(huì)造成外部碎片

內(nèi)部碎片和外部碎片對(duì)于查詢性能的影響

外部碎片對(duì)于性能的影響上面說(shuō)過(guò)仗颈,主要是在于需要進(jìn)行更多的跨區(qū)掃描,從而造成更多的IO操作.

而內(nèi)部碎片會(huì)造成數(shù)據(jù)行分布在更多的頁(yè)中怠堪,從而加重了掃描的頁(yè)樹揽乱,也會(huì)降低查詢性能.

下面通過(guò)一個(gè)例子看一下,我們?nèi)藶榈臑閯偛拍莻€(gè)表插入一些數(shù)據(jù)造成內(nèi)部碎片:

image-20210720092824007.png

通過(guò)查看碎片,我們發(fā)現(xiàn)這時(shí)碎片已經(jīng)達(dá)到了一個(gè)比較高的程度:


image-20210720092834247.png

通過(guò)查看對(duì)碎片整理之前和之后的IO粟矿,我們可以看出凰棉,IO大大下降了:


image-20210720092845879.png

對(duì)于碎片的解決辦法

基本上所有解決辦法都是基于對(duì)索引的重建和整理,只是方式不同

1.刪除索引并重建

這種方式并不好.在刪除索引期間陌粹,索引不可用.會(huì)導(dǎo)致阻塞發(fā)生撒犀。而對(duì)于刪除聚集索引,則會(huì)導(dǎo)致對(duì)應(yīng)的非聚集索引重建兩次(刪除時(shí)重建掏秩,建立時(shí)再重建).雖然這種方法并不好或舞,但是對(duì)于索引的整理最為有效

2.使用DROP_EXISTING語(yǔ)句重建索引

為了避免重建兩次索引,使用DROP_EXISTING語(yǔ)句重建索引蒙幻,因?yàn)檫@個(gè)語(yǔ)句是原子性的映凳,不會(huì)導(dǎo)致非聚集索引重建兩次,但同樣的邮破,這種方式也會(huì)造成阻塞

3.如前面文章所示诈豌,使用ALTER INDEX REBUILD語(yǔ)句重建索引

使用這個(gè)語(yǔ)句同樣也是重建索引,但是通過(guò)動(dòng)態(tài)重建索引而不需要卸載并重建索引.是優(yōu)于前兩種方法的抒和,但依舊會(huì)造成阻塞矫渔。可以通過(guò)ONLINE關(guān)鍵字減少鎖摧莽,但會(huì)造成重建時(shí)間加長(zhǎng).

4.使用ALTER INDEX REORGANIZE

這種方式不會(huì)重建索引庙洼,也不會(huì)生成新的頁(yè),僅僅是整理,當(dāng)遇到加鎖的頁(yè)時(shí)跳過(guò)油够,所以不會(huì)造成阻塞蚁袭。但同時(shí),整理效果會(huì)差于前三種.

理解填充因子

重建索引固然可以解決碎片的問(wèn)題.但是重建索引的代價(jià)不僅僅是麻煩叠聋,還會(huì)造成阻塞撕阎。影響使用.而對(duì)于數(shù)據(jù)比較少的情況下,重建索引代價(jià)并不大碌补。而當(dāng)索引本身超過(guò)百兆的時(shí)候。重建索引的時(shí)間將會(huì)很讓人蛋疼.

填充因子的作用正是如此棉饶。對(duì)于默認(rèn)值來(lái)說(shuō)厦章,填充因子為0(0和100表示的是一個(gè)概念),則表示頁(yè)面可以100%使用。所以會(huì)遇到前面update或insert時(shí)照藻,空間不足導(dǎo)致分頁(yè).通過(guò)設(shè)置填充因子袜啃,可以設(shè)置頁(yè)面的使用程度:


image-20210720092854184.png

下面來(lái)看一個(gè)例子:

還是上面那個(gè)表.我插入31條數(shù)據(jù),則占4頁(yè):


image-20210720092900986.png

通過(guò)設(shè)置填充因子幸缕,頁(yè)被設(shè)置到了5頁(yè)上:


image-20210720092916773.png

這時(shí)我再插入一頁(yè)群发,不會(huì)造成分頁(yè):


image-20210720092925941.png

上面的概念可以如下圖來(lái)解釋:


image-20210720092932611.png

可以看出,使用填充因子會(huì)減少更新或者插入時(shí)的分頁(yè)次數(shù)发乔,但由于需要更多的頁(yè)熟妓,則會(huì)對(duì)應(yīng)的損失查找性能.

如何設(shè)置填充因子的值

如何設(shè)置填充因子的值并沒(méi)有一個(gè)公式或者理念可以準(zhǔn)確的設(shè)置。使用填充因子雖然可以減少更新或者插入時(shí)的分頁(yè)栏尚,但同時(shí)因?yàn)樾枰嗟捻?yè)起愈,所以降低了查詢的性能和占用更多的磁盤空間.如何設(shè)置這個(gè)值進(jìn)行trade-off需要根據(jù)具體的情況來(lái)看.

具體情況要根據(jù)對(duì)于表的讀寫比例來(lái)看,我這里給出我認(rèn)為比較合適的值:

1.當(dāng)讀寫比例大于100:1時(shí),不要設(shè)置填充因子译仗,100%填充

2.當(dāng)寫的次數(shù)大于讀的次數(shù)時(shí)抬虽,設(shè)置50%-70%填充

3.當(dāng)讀寫比例位于兩者之間時(shí)80%-90%填充

上面的數(shù)據(jù)僅僅是我的看法,具體設(shè)置的數(shù)據(jù)還要根據(jù)具體情況進(jìn)行測(cè)試才能找到最優(yōu).

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纵菌,一起剝皮案震驚了整個(gè)濱河市阐污,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌咱圆,老刑警劉巖笛辟,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異闷堡,居然都是意外死亡隘膘,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門杠览,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)弯菊,“玉大人,你說(shuō)我怎么就攤上這事」芮” “怎么了钦铁?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)才漆。 經(jīng)常有香客問(wèn)我牛曹,道長(zhǎng),這世上最難降的妖魔是什么醇滥? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任黎比,我火速辦了婚禮,結(jié)果婚禮上鸳玩,老公的妹妹穿的比我還像新娘阅虫。我一直安慰自己,他們只是感情好不跟,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布颓帝。 她就那樣靜靜地躺著,像睡著了一般窝革。 火紅的嫁衣襯著肌膚如雪购城。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天虐译,我揣著相機(jī)與錄音瘪板,去河邊找鬼。 笑死菱蔬,一個(gè)胖子當(dāng)著我的面吹牛篷帅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拴泌,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼魏身,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了蚪腐?” 一聲冷哼從身側(cè)響起箭昵,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎回季,沒(méi)想到半個(gè)月后家制,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡泡一,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年颤殴,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鼻忠。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涵但,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情矮瘟,我是刑警寧澤瞳脓,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站澈侠,受9級(jí)特大地震影響劫侧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哨啃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一烧栋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧棘催,春花似錦劲弦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)次坡。三九已至呼猪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間砸琅,已是汗流浹背宋距。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留症脂,地道東北人谚赎。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像诱篷,于是被迫代替她去往敵國(guó)和親壶唤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容