隨著(zhù)海量數據時(shí)代的到來(lái),TB和EB級別的數據庫已經(jīng)出現在很多企業(yè)系統中。相對幾何級別增長(cháng)的數據量,存儲似乎是一個(gè)水漲船高不能填滿(mǎn)的空洞。數據表級別的壓縮,是一定程度上緩解海量數據存儲的一個(gè)解決方案。
在Oracle的產(chǎn)品發(fā)展歷程中,數據表壓縮compress技術(shù),一直是一個(gè)不斷提高和進(jìn)化的方面。在Oracle
1、Oracle Compression壓縮
簡(jiǎn)單的說(shuō),Oracle壓縮采用的是“重復值消除”(Eliminating Duplicate Values)算法。在數據庫塊級別,Oracle將壓縮數據保存在數據塊block中,解壓數據使用的所有信息也都保存在各自的數據塊內。如果存在數據行或者數據列重復的情況,只在塊頭保存一次。這些只保存一次的數據,稱(chēng)為“symbol table for that block”(該數據塊的符號表)。每個(gè)數據行如果使用這些符號表重復數據,只需要保存一個(gè)符號表記錄的“short reference”。
在Compression類(lèi)型上,Oracle根據數據表的操作類(lèi)型,提供兩種類(lèi)型的壓縮:
ü Compress for direct_load operation:直接路徑壓縮,也是默認的壓縮方式。該選項適合于Data warehouse類(lèi)型系統,該類(lèi)型系統沒(méi)有很頻繁的DML操作,數據加載方式也大都是使用批量加載;
ü Compress for all operation:是Advanced Compression的一個(gè)特點(diǎn)。通常的壓縮技術(shù)對于DML操作的影響是巨大的。Advanced Compression的這個(gè)選擇類(lèi)型,就是為OLTP系統準備。該選項為所有的DML操作開(kāi)啟了壓縮功能;
2、Advanced Compression適應范圍
Oracle
ü OLTP數據表壓縮
Oracle最早從9i版本中,提供了壓縮compression功能。早期的compression允許數據表在進(jìn)行批量加載操作(bulk load operation)是對數據進(jìn)行壓縮,比如direct path load(sql loader)、create table as select…操作(CTAS)。這種方式適應數據倉庫(Data warehouse)類(lèi)型系統。
Advanced Compression技術(shù)組件提供了對各種類(lèi)型操作進(jìn)行壓縮的技術(shù),包括了常規的DML insert和update操作。具體包括下列操作:
1) 直接路徑加載,如sql loader;
2) Create table xxx as select xx操作(CTAS);
3) 并行parallel(或者串行使用append提示的插入)語(yǔ)句;
4) 單行或者多行插入;
5) 單行或者多行更新;
在使用一些數據管理語(yǔ)句,如move操作的時(shí)候,在執行階段就會(huì )對數據表加以exclusive級別數據鎖,禁止進(jìn)行DML操作。操作結束時(shí),數據表還是能夠保證壓縮狀態(tài)。
對壓縮數據表,進(jìn)行DML操作的性能損耗可以做到最小。這也是Advanced Compression最大特色。
ü Secure File壓縮和消重復(Compression and DeDuplication)
Secure File Deduplication是用于消除重復Secur File數據的智能化技術(shù)。Oracle可以將重復的多份Secure File數據只保存一份,其他保存都是對該文件的一個(gè)鏡像引用。這樣做就可以大大減少空間占用。
ü Data Dump數據泵壓縮
數據泵data dump是Oracle
ü RMAN壓縮
RMAN是Oracle主推的備份還原工具在寫(xiě)入磁盤(pán)disk或者磁帶tape之前,就已經(jīng)是壓縮過(guò)的備份數據。在進(jìn)行還原操作的時(shí)候,是不要進(jìn)行顯示的解壓工作。這樣對于保存的完全、增量備份集合set來(lái)說(shuō),是非常好的優(yōu)質(zhì)特性。
ü DataGuard Network Compress
DataGuard是Oracle HA(High Availability)的重要組成部分。Primary Database和Standby Database之間,通過(guò)網(wǎng)絡(luò )建立實(shí)時(shí)連接。Primary Database的任何數據變化,都會(huì )以redo log的方式持續傳入到standby database上,進(jìn)行apply應用過(guò)程。最終實(shí)現一致性。
使用Oracle Advanced Compression技術(shù),可以對網(wǎng)路中傳輸的redo data進(jìn)行壓縮,從而減少redo gap。最終讓standby database可以更快的進(jìn)行同步,實(shí)現HA目標。
最后特別說(shuō)一下關(guān)于Advanced Compression lisence問(wèn)題,在
下面我們通過(guò)一系列實(shí)驗來(lái)演示table compression的使用。
3、實(shí)驗環(huán)境準備
首先我們準備實(shí)驗環(huán)境,構建一個(gè)相對較大的數據表。
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database
PL/SQL Release
CORE
TNS for Linux: Version
NLSRTL Version
SQL> select * from v$option where parameter='Advanced Compression';
PARAMETER VALUE
-------------------- ----------------------------------------------------------------
Advanced Compression TRUE
構建數據表t_ori,其中包括21萬(wàn)余條數據。
SQL> create table t_ori as select * from dba_objects;
Table created
SQL> select count(*) from t_ori;
COUNT(*)
----------
217731
SQL> exec dbms_stats.gather_table_stats(user,'T_ORI',cascade => true);
PL/SQL procedure successfully completed
從數據字典中,我們可以清晰的看到數據表空間分配。
SQL> select segment_name, count(*) extents, sum(blocks) blocks,sum(bytes)/1024/1024 MBs from dba_extents where wner='SYS' and segment_name='T_ORI' group by segment_name;
SEGMENT_NAME EXTENTS BLOCKS MBS
-------------------- ---------- ---------- ----------
T_ORI 40 3200 25
SQL> SELECT table_name, compression, compress_for FROM dba_tables where table_name='T_ORI';
TABLE_NAME COMPRESSION COMPRESS_FOR
------------------------------ ----------- ------------
T_ORI DISABLED
4、Compress For Direct_Load Operation
首先我們使用compress常規選項。
SQL> create table t_compresscompressas select * from t_ori where 1=0;
Table created
SQL> SELECT table_name, compression, compress_for FROM dba_tables where table_name in ('T_ORI','T_COMPRESS');
TABLE_NAME COMPRESSION COMPRESS_FOR
------------------------------ ----------- ------------
T_ORI DISABLED
T_COMPRESS ENABLED BASIC
在創(chuàng )建數據表時(shí),使用compress子句,就可以創(chuàng )建出具有壓縮功能的數據表。從數據字典看,T_COMPRESS開(kāi)啟了壓縮功能,是Basic類(lèi)型。
Compress對應的就是compress for direct_load operations壓縮類(lèi)型。使用傳統的壓縮方式,適合data warehouse類(lèi)型。
SQL> create table t_compdir compress for direct_load operations as select * from t_ori;
Table created
Executed in 0.829 seconds
SQL> SELECT table_name, compression, compress_for FROM dba_tables where table_name in ('T_ORI','T_COMPRESS', 'T_COMPDIR');
TABLE_NAME COMPRESSION COMPRESS_FOR
------------------------------ ----------- ------------
T_COMPDIR ENABLED BASIC
T_ORI DISABLED
T_COMPRESS ENABLED BASIC
如果對數據表使用append方式添加數據,是使用direct load加載數據。
SQL> insert/*+append */into t_compress select * from t_ori;
217731 rows inserted
Executed in 0.563 seconds
SQL> commit;
Commit complete
Executed in 0 seconds
SQL> select segment_name, count(*) extents, sum(blocks) blocks,sum(bytes)/1024/1024 MBs from dba_extents where wner='SYS' and segment_name in ('T_ORI','T_COMPRESS','T_COMPDIR') group by segment_name;
SEGMENT_NAME EXTENTS BLOCKS MBS
-------------------- ---------- ---------- ----------
T_COMPDIR 22 896 7
T_COMPRESS 37 2816 22
T_ORI 40 3200 25
Executed in 0.078 seconds
上面實(shí)驗,我們可以對比出在進(jìn)行不同操作時(shí)advanced compression的特性。對于compress for direct_load operations操作,使用CTAS操作的壓縮率較高。原數據表大小為
但是,如果使用append提示進(jìn)行插入操作,雖然也會(huì )有壓縮效果,但是壓縮效果遠不如CTAS,壓縮后的數據表為
SQL> truncate table t_compress;
Table truncated
SQL> declare
2 type t_list is table of t_ori%rowtype index by binary_integer;
3 i integer;
4
5 t_infos t_list;
6 begin
7 select *
8 bulk collect into t_infos
9 from t_ori;
10
11 for i in 1..t_infos.count loop
12 insert into T_COMPRESS values t_infos(i);
13
14 if (mod(i,1000)=0) then
15 commit;
16 end if;
17 end loop;
18
19 commit;
20 end;
21 /
PL/SQL procedure successfully completed
Executed in 18.703 seconds
SQL> select segment_name, count(*) extents, sum(blocks) blocks,sum(bytes)/1024/1024 MBs from dba_extents where wner='SYS' and segment_name in ('T_ORI','T_COMPRESS','T_COMPDIR') group by segment_name;
SEGMENT_NAME EXTENTS BLOCKS MBS
-------------------- ---------- ---------- ----------
T_COMPDIR 22 896 7
T_COMPRESS 37 2816 22
T_ORI 40 3200 25
Executed in 0.062 seconds
從現象上看,使用append數據表時(shí)和普通insert數據表在T_COMPRESS的時(shí)候空間差異不大。
下面我們來(lái)實(shí)驗使用compress for direct_load operations的時(shí)候,對其他操作影響。
SQL> alter system flush buffer_cache;
System altered
SQL> select count(*) from t_compress;
COUNT(*)
----------
217731
Executed in0.094seconds
SQL> select count(*) from t_compdir;
COUNT(*)
----------
217731
Executed in0.063seconds
SQL> select count(*) from t_ori;
COUNT(*)
----------
217731
Executed in0.031seconds
從查詢(xún)時(shí)間看,普通compress雖然可以大幅度減少空間使用,但是對其他操作的影響是存在的。
5、Compress For All Operation
Compress For All Operation選項是Advanced Compression的重要進(jìn)步,提供了OLTP類(lèi)型的壓縮操作。
SQL> create table t_compall compress for all operations as select * from t_ori where 1=0;
Table created
Executed in 0.157 seconds
SQL> create table t_compall2 compress for all operations as select * from t_ori;
Table created
Executed in 0.797 seconds
使用Compress for all operations子句就可以建立壓縮數據表。
SQL> insert /*+append */into t_compall select * from t_ori;
217731 rows inserted
Executed in 0.797 seconds
SQL> commit;
Commit complete
Executed in 0 seconds
SQL> select segment_name, count(*) extents, sum(blocks) blocks,sum(bytes)/1024/1024 MBs from dba_extents where wner='SYS' and segment_name in ('T_ORI','T_COMPALL','T_COMPALL2') group by segment_name;
SEGMENT_NAME EXTENTS BLOCKS MBS
-------------------- ---------- ---------- ----------
T_COMPALL2 23 1024 8
T_COMPALL 40 3200 25
T_ORI 40 3200 25
Executed in 0.797 seconds
同compress for direct_load operations現象基本類(lèi)似。Append方式插入表現出一般的壓縮比例。
SQL> truncate table t_compall;
Table truncated
Executed in 0.047 seconds
SQL> declare
2 type t_list is table of t_ori%rowtype index by binary_integer;
3 i integer;
4
5 t_infos t_list;
6 begin
7 select *
8 bulk collect into t_infos
9 from t_ori;
10
11 for i in 1..t_infos.count loop
12 insert into t_compall values t_infos(i);
13
14 if (mod(i,1000)=0) then
15 commit;
16 end if;
17 end loop;
18
19 commit;
20 end;
21 /
PL/SQL procedure successfully completed
Executed in 17.687 seconds
SQL> select segment_name, count(*) extents, sum(blocks) blocks,sum(bytes)/1024/1024 MBs from dba_extents where wner='SYS' and segment_name in ('T_ORI','T_COMPALL','T_COMPALL2') group by segment_name;
SEGMENT_NAME EXTENTS BLOCKS MBS
-------------------- ---------- ---------- ----------
T_COMPALL2 23 1024 8
T_COMPALL 40 3200 25
T_ORI 40 3200 25
Executed in 0.313 seconds
6、結論
Oracle
聯(lián)系客服