這篇文章將為大家詳細(xì)講解有關(guān)Oracle如何修改壓縮數(shù)據(jù),小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
創(chuàng)新互聯(lián)建站是一家集網(wǎng)站建設(shè),觀山湖企業(yè)網(wǎng)站建設(shè),觀山湖品牌網(wǎng)站建設(shè),網(wǎng)站定制,觀山湖網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營(yíng)銷(xiāo),網(wǎng)絡(luò)優(yōu)化,觀山湖網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競(jìng)爭(zhēng)力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長(zhǎng)自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
我們將看到只有在直接路徑加載、CTAS(create table as select)和"alter table move"時(shí),基礎(chǔ)表壓縮機(jī)制才可以生效。同時(shí)當(dāng)表啟用了壓縮時(shí),Oracle會(huì)默認(rèn)的將該表中數(shù)據(jù)塊的pctfree設(shè)置為0,這也暗示了我們基礎(chǔ)壓縮應(yīng)該作為一種只讀數(shù)據(jù)的壓縮策略。
當(dāng)我們查看一個(gè)對(duì)應(yīng)塊的dump文件時(shí),會(huì)發(fā)現(xiàn)Oracle并不是“壓縮”數(shù)據(jù),他所做的是在每個(gè)塊上創(chuàng)建重復(fù)值列表(即字典表),然后通過(guò)一些標(biāo)志來(lái)代替那些重復(fù)值從而達(dá)到塊級(jí)別的去重。并且,Oracle可以重新排列塊中的字段順序,從而增加用一個(gè)標(biāo)志來(lái)代替多個(gè)字段的機(jī)會(huì)。這告訴我們,Oracle在讀取塊時(shí)并不需要“解壓”數(shù)據(jù),他需要做的僅僅是通過(guò)指針來(lái)重構(gòu)數(shù)據(jù),當(dāng)然這是一個(gè)CPU密集型操作。
在這篇文章中,我們將討論如果不遵從只讀原則將會(huì)發(fā)生什么。然后,我們將會(huì)在第三篇文章中探討需要另外授權(quán)的OLTP壓縮。如前所述,以下所有示例都來(lái)自O(shè)racle 11.2.0.3的實(shí)例。
去重與刪除
你可以回憶下上篇文章中,我把一個(gè)包含組合標(biāo)志的數(shù)據(jù)塊的一行dump出來(lái),然后Oracle遞歸的向上查找這個(gè)標(biāo)志代表的意義,最終確定該組合標(biāo)志由兩個(gè)單獨(dú)的標(biāo)志和兩個(gè)額外的字段值組合而成,下面就是我們測(cè)試的那行:
tab 1, row 0, @0x1b28
tl: 5 fb: --H-FL-- lb: 0x0 cc: 4
col 0: [ 4] 41 41 41 41
col 1: [10] 41 41 41 41 41 41 41 41 41 41
col 2: [ 2] c1 02
col 3: [10] 20 20 20 20 20 20 20 20 20 31
bindmp: 2c 00 01 04 31
這是我們?cè)诓檎乙玫膯蝹€(gè)標(biāo)志的值時(shí)所發(fā)現(xiàn)的**49號(hào)標(biāo)志**:
Tab 0, row 49, @0x1ed0
tl: 19 fb: --H-FL-- lb: 0x0 cc: 4
col 0: [ 4] 41 41 41 41
col 1: [10] 41 41 41 41 41 41 41 41 41 41
col 2: [ 2] c1 02
col 3: [10] 20 20 20 20 20 20 20 20 20 31
bindmp: 00 08 04 36 40 ca c1 02 d2 20 20 20 20 20 20 20 20 20 31
bindmp中的前5個(gè)字節(jié)告訴我們這個(gè)標(biāo)志在這個(gè)塊中使用了8次(00 08),由4個(gè)列組成,然后我們來(lái)看看54(0x36)和64(0x40)號(hào)標(biāo)志:
tab 0, row 54, @0x1f74
tl: 7 fb: --H-FL-- lb: 0x0 cc: 1
col 0: [ 4] 41 41 41 41
bindmp: 00 0a cc 41 41 41 41
tab 0, row 64, @0x1f7b
tl: 13 fb: --H-FL-- lb: 0x0 cc: 1
col 0: [10] 41 41 41 41 41 41 41 41 41 41
bindmp: 00 05 d2 41 41 41 41 41 41 41 41 41 41
從上面的dump數(shù)據(jù)我們可以猜到,如果想要?jiǎng)h除原始行,就必須進(jìn)行額外的工作。 \
有兩件事必然會(huì)發(fā)生:
1. 該行必須標(biāo)志為已刪除(以正常的方式),
2. **49號(hào)標(biāo)志**的“使用計(jì)數(shù)”也必須減少1。
在刪除一行之后,這里有一個(gè)小的片段,首先是行條目本身:
tab 1, row 0, @0x1b28
tl: 2 fb: --HDFL-- lb: 0x2
bindmp: 3c 02
以下是**49號(hào)標(biāo)志**的二進(jìn)制轉(zhuǎn)儲(chǔ),注意,第二個(gè)字節(jié):
bindmp: 00 07 04 36 40 ca c1 02 d2 20 20 20 20 20 20 20 20 20 31
所以我們可以意識(shí)到,即使是刪除簡(jiǎn)單的一行,也會(huì)使維護(hù)塊數(shù)據(jù)的工作增加。但是這個(gè)標(biāo)志同時(shí)也在塊的其他7行中使用,所以如果我刪除這些行,會(huì)發(fā)生什么?答案取決于刪除的并發(fā)會(huì)話數(shù)量。如果我使用一個(gè)進(jìn)程來(lái)刪除所有8行,在刪除第8行時(shí),Oracle刪除了標(biāo)志,此時(shí)63號(hào)標(biāo)志和64號(hào)標(biāo)志必須更新,以顯示它們?nèi)鄙倭艘粋€(gè)依賴項(xiàng)。如果我重復(fù)測(cè)試使用多個(gè)會(huì)話來(lái)刪除行,并且在每次刪除后不提交,那么我就可以看到一個(gè)場(chǎng)景,標(biāo)志顯示為零,但不會(huì)消失。(也有可能我還沒(méi)有觀察到的一些后續(xù)的塊清理操作將會(huì)清除這個(gè)狀態(tài)的標(biāo)志。)
在我提到并發(fā)測(cè)試之前,我沒(méi)有提到任何關(guān)于提交或回滾的內(nèi)容。標(biāo)志的改變發(fā)生在delete這個(gè)動(dòng)作上,并且之后并沒(méi)有提交。如果我提交或回滾會(huì)發(fā)生什么?
在提交時(shí),可能會(huì)發(fā)生通常的提交清除操作,用提交時(shí)的SCN更新事務(wù)的ITL插槽(換句話說(shuō),沒(méi)有新的或特別的事情發(fā)生)。在回滾時(shí),數(shù)據(jù)根據(jù)undo信息恢復(fù),任何已經(jīng)被刪除的標(biāo)志也將被重新創(chuàng)建,任何相關(guān)標(biāo)志的使用數(shù)都會(huì)增加。
但重點(diǎn)是,回滾之后,壓縮依然會(huì)保留。雖然這些行會(huì)在回滾后寫(xiě)入塊的空閑空間,但在原始?jí)K和回滾后的塊之間還是有一些區(qū)別。因?yàn)檫@樣的操作需要塊經(jīng)過(guò)空閑空間碎片的整合操作。所以如果你再次將塊dump出來(lái),你可以看到塊的內(nèi)容已經(jīng)被移動(dòng)了。在我的例子里(刪除了引用49號(hào)標(biāo)志的8行記錄,然后回滾),我看到了如下的區(qū)別:
tab 0, row 49, @0x1ed0 -- original position of token 0
tab 0, row 49, @0x134a -- position of token 0 after rollback
tab 1, row 0, @0x1b28 -- original position of row 0
tab 1, row 0, @0x1322 -- position of row 0 after rollback
壓縮與空閑空間
當(dāng)你刪除然后回滾數(shù)據(jù)后,行就會(huì)移動(dòng),這個(gè)現(xiàn)象引出了關(guān)于空閑空間非常有趣的一點(diǎn)——當(dāng)你的表是基礎(chǔ)壓縮的時(shí)候,默認(rèn)的pctfree就是0了。沒(méi)有空閑空間,但有空間給我在回滾后移動(dòng)數(shù)據(jù)用?
我發(fā)現(xiàn)Oracle確實(shí)會(huì)保留一點(diǎn)點(diǎn)空間(大約幾十byte,但對(duì)于我測(cè)試用例里的兩整行也是絕對(duì)足夠了)。這一小部分空間允許Oracle恢復(fù)那些已被刪除的行。有些情況,這部分剩余空間甚至能讓你做update操作。
我來(lái)微調(diào)下我的初始數(shù)據(jù)集,每一行看起來(lái)如下:
(1000001, 'AAAA', 'AAAAAAAAAA',' 1')
第一列是一個(gè)序列,第二列從AAAA到EEEE循環(huán),第三列從AAAAAAAAAA到JJJJJJJJJJ循環(huán),最后一列是10個(gè)字符,從1-50循環(huán)(占位符用"\ "表示)。然后我生成800行數(shù)據(jù)。由于我創(chuàng)建數(shù)據(jù)的方法問(wèn)題,第一個(gè)數(shù)據(jù)塊中有11行數(shù)據(jù),第二第三列都是A,所以我需要運(yùn)行如下sql然后dump表中的第一個(gè)塊來(lái)觀察發(fā)生了什么。
update t1
set
vc_rep = 'BBBB'
where
vc_rep = 'AAAA'
and vc_cycle = 'AAAAAAAAAA'
and rownum <= 4
;
這證明了這個(gè)塊里有足夠的空間來(lái)更新這兩行記錄,而且始終在同一個(gè)塊里,但是我的行還是發(fā)生了遷移。這里有這個(gè)數(shù)據(jù)塊中某行在操作前后的dump數(shù)據(jù)對(duì)比:
tab 1, row 0, @0x1bb8 -- before
tl: 11 fb: --H-FL-- lb: 0x0 cc: 4
col 0: [ 4] 41 41 41 41
col 1: [10] 41 41 41 41 41 41 41 41 41 41
col 2: [10] 20 20 20 20 20 20 20 20 20 31
col 3: [ 5] c4 02 01 01 02
bindmp: 2c 00 02 03 1b cd c4 02 01 01 02
tab 1, row 0, @0x4f3 -- after
tl: 37 fb: --H-FL-- lb: 0x2 cc: 4
col 0: [ 4] 42 42 42 42
col 1: [10] 41 41 41 41 41 41 41 41 41 41
col 2: [10] 20 20 20 20 20 20 20 20 20 31
col 3: [ 5] c4 02 01 01 02
bindmp: 2c 02 04 00 cc 42 42 42 42 d2 41 41 41 41 41 41 41 41 41 41 d2 20 20 20 20 20 20 20 20 20 31 cd c4 02 01 01 02
在update操作后,Oracle將該行擴(kuò)展成了完整的四列數(shù)據(jù)。有兩個(gè)標(biāo)志在字典表中,可以被用來(lái)替換更新的這行記錄的前兩個(gè)字段。但是Oracle并沒(méi)有去試圖尋找并使用這些標(biāo)志。所以,這么看來(lái),好像update壓縮的數(shù)據(jù)就會(huì)造成整體的混亂,一行壓縮的記錄可能會(huì)擴(kuò)展的及其巨大,微不足道的那點(diǎn)空閑空間無(wú)法裝下這些數(shù)據(jù),最終引發(fā)了行的遷移。
雖然我們現(xiàn)在看來(lái),當(dāng)出現(xiàn)擴(kuò)展的行以及遷移的行之后,數(shù)據(jù)會(huì)有點(diǎn)混亂。但當(dāng)我們執(zhí)行回滾操作時(shí),Oracle會(huì)把這些混亂清理干凈,而且剩余的行也都會(huì)在原始?jí)嚎s的、未遷移的位置。
所以u(píng)pdate操作到底能造成多么糟糕的影響?回答這個(gè)問(wèn)題之前,我們可以先看下我所做的update操作。我修改了一個(gè)標(biāo)志可以代替的值,而且該值在很多行中都存在。但如果我修改了一個(gè)標(biāo)志無(wú)法代替的值呢?Oracle還會(huì)因?yàn)檫@個(gè)update來(lái)擴(kuò)展這行記錄嗎?答案是否定的。如果我們修改了ID(序列類型,不重復(fù),無(wú)法標(biāo)志化)的值。下面是修改前會(huì)的dump數(shù)據(jù)對(duì)比:
tab 1, row 0, @0x1bb8 -- before
tl: 11 fb: --H-FL-- lb: 0x0 cc: 4
col 0: [ 4] 41 41 41 41
col 1: [10] 41 41 41 41 41 41 41 41 41 41
col 2: [10] 20 20 20 20 20 20 20 20 20 31
col 3: [ 5] c4 02 01 01 02
bindmp: 2c 00 02 03 1b cd c4 02 01 01 02
tab 1, row 0, @0x1bb8 -- after
tl: 10 fb: --H-FL-- lb: 0x2 cc: 4
col 0: [ 4] 41 41 41 41
col 1: [10] 41 41 41 41 41 41 41 41 41 41
col 2: [10] 20 20 20 20 20 20 20 20 20 31
col 3: [ 4] c3 64 64 64
bindmp: 2c 02 02 03 1b cc c3 64 64 64
update操作后的數(shù)據(jù)依然在原來(lái)的位置,并未發(fā)生遷移。但是請(qǐng)注意該行由一個(gè)可代表前三行的標(biāo)志和一個(gè)實(shí)際的值組成。行擴(kuò)展并未發(fā)生。
我初始測(cè)試的那行數(shù)據(jù)實(shí)際上整行都可以被一個(gè)標(biāo)志所代替。如果我更新一個(gè)被多個(gè)標(biāo)志組合起來(lái)的行中的某個(gè)標(biāo)志化的字段會(huì)怎樣?Oracle并不會(huì)擴(kuò)展整行——它只會(huì)擴(kuò)展update操作影響的那列的數(shù)據(jù)。這里是操作前后的dump數(shù)據(jù):
tab 1, row 18, @0x1ac2
tl: 13 fb: --H-FL-- lb: 0x0 cc: 4
col 0: [ 4] 44 44 44 44
col 1: [10] 58 58 58 58 58 58 58 58 58 58
col 2: [10] 20 20 20 20 20 20 20 20 33 34
col 3: [ 5] c4 02 01 01 14
bindmp: 2c 00 04 03 32 37 45 cd c4 02 01 01 14
tab 1, row 18, @0x1ab8
tl: 23 fb: --H-FL-- lb: 0x2 cc: 4
col 0: [ 4] 44 44 44 44
col 1: [10] 59 59 59 59 59 59 59 59 59 59
col 2: [10] 20 20 20 20 20 20 20 20 33 34
col 3: [ 5] c4 02 01 01 14
bindmp: 2c 02 04 00 32 d2 59 59 59 59 59 59 59 59 59 59 45 cd c4 02 01 01 14
在這個(gè)測(cè)試的最開(kāi)始,dump數(shù)據(jù)就表明了這行由三個(gè)獨(dú)立的標(biāo)志(0x32, 0x37和0x45)和一個(gè)實(shí)際數(shù)值組成。我將第一列的值‘XXXXXXXXXX’更新為‘YYYYYYYYYY’,正如你所見(jiàn),最后一塊dump數(shù)據(jù)依然包含標(biāo)志0x32和0x45,但是標(biāo)志0x37已經(jīng)被實(shí)際值所替換掉。你也可以看到行的長(zhǎng)度增加了10字節(jié)(從13b增加到23b),這意味著Oracle不得不把它移動(dòng)到那很小的一部分空閑空間中,所以最終行的地址發(fā)生了變化。
所以當(dāng)你試圖更新基礎(chǔ)表壓縮中的數(shù)據(jù)時(shí),Oracle可能將標(biāo)志擴(kuò)展為實(shí)際值,但它會(huì)盡可能的做最小化的擴(kuò)展。即使數(shù)據(jù)在壓縮后pctfree為0的情況下數(shù)據(jù)塊中依然有一小部分空間。所以雖然你可以在不造成大量擴(kuò)展以及行遷移的情況下做一些極小量的update操作,但這些副作用幾乎不可能被預(yù)知。
如果你確實(shí)需要對(duì)已壓縮的數(shù)據(jù)做一些小量的維護(hù)操作,就需要對(duì)實(shí)際數(shù)據(jù)做足夠多的測(cè)試來(lái)尋找最合適的pctfree的值,以將行遷移率控制在可接受的范圍。
關(guān)于“Oracle如何修改壓縮數(shù)據(jù)”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。