從底向上第五篇--瞭解表的壓縮屬性
從底向上第一篇--瞭解DML操作
從底向上第二篇--瞭解行遷移
從底向上第三篇--瞭解index的compress
從底向上第四篇--瞭解行連結
從底向上第五篇--瞭解表的壓縮屬性
在從底向上第三篇--瞭解index的compress中,我們看到了對於索引而言,使用compress屬性是如何改變索引的儲存方式的。
這裡,對錶的compress及compress的適用情況做一下測試。
SQL> conn test/test
已連線。
SQL> create table t compress as select * from dba_tables where 1=0; --以compress關鍵字建立一個空表
表已建立。
SQL> insert into t select * from dba_tables; -- 插入資料
已建立3003行。
SQL> commit;
提交完成。
按照正常邏輯,我們已經指定了compress關鍵字,那麼,表應該是壓縮了的。我們看一下。
SQL> select segment_name,blocks,header_file,header_block from dba_segments where
segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS HEADER_FILE HEADER_BLOCK
---------- ----------- ------------
T
96 4 794
SQL> alter system dump datafile 4 block 795;
系統已更改。[@more@]data_block_dump,data header at 0x20566064
===============
tsiz: 0x1f98
hsiz: 0x5a
pbl: 0x20566064
76543210
flag=-------- -- 沒有壓縮塊標誌
ntab=1 -- 塊內只有一個表
nrow=36 -- 這個塊放了36行資料
frre=-1
fsbo=0x5a
fseo=0x6d
avsp=0x13
tosp=0x13
0xe:pti[0] nrow=36 offs=0
0x12:pri[0] offs=0x1df4
…
block_row_dump:
SQL> select count(*) from t;
COUNT(*)
----------
3002
執行計劃
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T | 2977 | 30 (0)| 00:00:01 |
-------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
統計資訊
----------------------------------------------------------
0 recursive calls
0 db block gets
98 consistent gets
0 physical reads
0 redo size
420 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
Ok,上面的例子裡,簡單的插入並不能啟動compress,那麼應該怎樣做,才能使表進行壓縮呢?
SQL> conn test/test
已連線。
SQL> truncate table t;
表被截斷。
SQL> insert /*+ append */ into t select * from dba_tables; -- 使用直接路徑插入
已建立3003行。
SQL> commit;
提交完成。
SQL> select header_file,header_block from dba_segments where segment_name='T';
HEADER_FILE HEADER_BLOCK
----------- ------------
4 538
SQL> select segment_name,blocks from dba_segments where segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS
----------
T
16
對於這個表,壓縮比率是多少呢?16/96 大概16.7%的樣子。
SQL> alter system dump datafile 4 block 539;
系統已更改。
data_block_dump,data header at 0xd2d827c
===============
tsiz: 0x1f80
hsiz: 0x38e
pbl: 0x0d2d827c
76543210
flag=-0------ -- 標誌O表示這個塊是壓縮塊
ntab=2 -- 塊內有兩個表,為什麼是兩個表呢?其實,一個是字典表,一個是資料表(字典的引用)
nrow=384 -- 塊記憶體儲了384行資料
frre=-1
fsbo=0x38e
fseo=0x441
avsp=0xb3
tosp=0xb3
-- 下面是壓縮塊獨有的內容:
r0_9ir2=0x0
mec_kdbh9ir2=0x37
76543210
shcf_kdbh9ir2=----------
76543210
flag_9ir2=--R---OC
fcls_9ir2[30]={ 0 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 }
perm_9ir2[51]={ 27 50 26 44 0 1 39 42 40 28 43 41 2 3 4 29 30 5 6 48 45 31 32 33 46 34 35 7 8 9 10 49 47 11 12 13 14 15 16 36 37 17 18 19 20 38 21 22 23 24 25 }
0x86:pti[0] nrow=144 offs=0
0x8a:pti[1] nrow=240 offs=144
0x8e:pri[0] offs=0x1b21
…
block_row_dump:
tab 0, row 141, @0x1ea2 -- tab0 字典表
tl: 10 fb: --H-FL-- lb: 0x0 cc: 1
col 0: [ 7] 78 6e 03 15 12 0f 29
bindmp: 00 02 cf 78 6e 03 15 12 0f 29 -- bindmp,原始資料匯出,真正儲存的是這個
…
tab 1, row 0, @0x1a50 --tab1 資料表
tl: 22 fb: --H-FL-- lb: 0x0 cc: 51 --壓縮後行的大小是22
-- 以下col都是恢復(解壓縮)出來的內容
col 0: *NULL*
col 1: [ 5] 56 41 4c 49 44
col 2: [ 2] c1 02
col 3: [ 6] c5 16 30 31 25 2e
col 4: *NULL*
col 5: [ 3] 59 45 53
col 6: [ 1] 4e
col 7: [10] 20 20 20 20 20 20 20 20 20 31
col 8: [10] 20 20 20 20 20 20 20 20 20 31
col 9: [ 5] 20 20 20 20 4e
…
col 50: [10] 54 59 50 45 5f 4d 49 53 43 24
-- 以下是行實際儲存資料
bindmp: 2c 00 06 1d 03 ca c1 2f 44 6b 6b d2 54 59 50 45 5f 4d 49 53 43 24
SQL> select count(*) from t;
COUNT(*)
----------
3002
執行計劃
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 6 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T | 3002 | 6 (0)| 00:00:01 |
-------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
統計資訊
----------------------------------------------------------
0 recursive calls
0 db block gets
15 consistent gets
0 physical reads
0 redo size
420 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
由於表資料進行了壓縮,資料塊大小由96降為16,全表掃描的Cost也由30降到了6,。
Ok,既然資料已經進行了壓縮,那麼,我們在這個已經壓縮的表上再次正常insert資料,看看會不會壓縮?
SQL> insert into t select * from dba_tables;
已建立3003行。
SQL> commit;
提交完成。
SQL> select segment_name,blocks from dba_segments where segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS
----------
T
112
SQL> alter system dump datafile 4 block 555;
系統已更改。
data_block_dump,data header at 0x2056c064
===============
tsiz: 0x1f98
hsiz: 0x5a
pbl: 0x2056c064
76543210
flag=-------- -- 不是壓縮塊
ntab=1
nrow=36
frre=-1
fsbo=0x5a
fseo=0xac
avsp=0x52
tosp=0x52
0xe:pti[0] nrow=36 offs=0
0x12:pri[0] offs=0x1b55
…
block_row_dump:
即使表中已存在的內容是壓縮的,後續未採用直接路徑insert的資料依然不能壓縮。
SQL> conn test/test
已連線。
SQL> drop table t;
表已刪除。
SQL> create table t compress as select * from dba_tables;
表已建立。
SQL> select segment_name,blocks from dba_segments where segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS
----------
T
16
CTAS可以壓縮表資料。
綜上,對於壓縮表而言,使用範圍要比壓縮索引小的多,僅僅適用於CTAS或直接路徑載入插入。
並且,一般而言,壓縮表由於降低了表的Block數量,直接降低了邏輯讀,雖然壓縮、解壓縮過程會使用額外的CPU資源,但往往是利大於弊。個人認為,對於系統中常用的碼錶(不容易修改,並且資料量不會太大)壓縮可以作為降低資源使用的一種方法。
值得注意的是,對於exp/imp而言,因為無法做直接路徑載入,將會導致壓縮表在匯出、匯入後以正常表來進行儲存。
關於更深入的瞭解壓縮塊的格式,老熊有個很好的文章,請移步
從底向上第二篇--瞭解行遷移
從底向上第三篇--瞭解index的compress
從底向上第四篇--瞭解行連結
從底向上第五篇--瞭解表的壓縮屬性
在從底向上第三篇--瞭解index的compress中,我們看到了對於索引而言,使用compress屬性是如何改變索引的儲存方式的。
這裡,對錶的compress及compress的適用情況做一下測試。
SQL> conn test/test
已連線。
SQL> create table t compress as select * from dba_tables where 1=0; --以compress關鍵字建立一個空表
表已建立。
SQL> insert into t select * from dba_tables; -- 插入資料
已建立3003行。
SQL> commit;
提交完成。
按照正常邏輯,我們已經指定了compress關鍵字,那麼,表應該是壓縮了的。我們看一下。
SQL> select segment_name,blocks,header_file,header_block from dba_segments where
segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS HEADER_FILE HEADER_BLOCK
---------- ----------- ------------
T
96 4 794
SQL> alter system dump datafile 4 block 795;
系統已更改。[@more@]data_block_dump,data header at 0x20566064
===============
tsiz: 0x1f98
hsiz: 0x5a
pbl: 0x20566064
76543210
flag=-------- -- 沒有壓縮塊標誌
ntab=1 -- 塊內只有一個表
nrow=36 -- 這個塊放了36行資料
frre=-1
fsbo=0x5a
fseo=0x6d
avsp=0x13
tosp=0x13
0xe:pti[0] nrow=36 offs=0
0x12:pri[0] offs=0x1df4
…
block_row_dump:
SQL> select count(*) from t;
COUNT(*)
----------
3002
執行計劃
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 30 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T | 2977 | 30 (0)| 00:00:01 |
-------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
統計資訊
----------------------------------------------------------
0 recursive calls
0 db block gets
98 consistent gets
0 physical reads
0 redo size
420 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
Ok,上面的例子裡,簡單的插入並不能啟動compress,那麼應該怎樣做,才能使表進行壓縮呢?
SQL> conn test/test
已連線。
SQL> truncate table t;
表被截斷。
SQL> insert /*+ append */ into t select * from dba_tables; -- 使用直接路徑插入
已建立3003行。
SQL> commit;
提交完成。
SQL> select header_file,header_block from dba_segments where segment_name='T';
HEADER_FILE HEADER_BLOCK
----------- ------------
4 538
SQL> select segment_name,blocks from dba_segments where segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS
----------
T
16
對於這個表,壓縮比率是多少呢?16/96 大概16.7%的樣子。
SQL> alter system dump datafile 4 block 539;
系統已更改。
data_block_dump,data header at 0xd2d827c
===============
tsiz: 0x1f80
hsiz: 0x38e
pbl: 0x0d2d827c
76543210
flag=-0------ -- 標誌O表示這個塊是壓縮塊
ntab=2 -- 塊內有兩個表,為什麼是兩個表呢?其實,一個是字典表,一個是資料表(字典的引用)
nrow=384 -- 塊記憶體儲了384行資料
frre=-1
fsbo=0x38e
fseo=0x441
avsp=0xb3
tosp=0xb3
-- 下面是壓縮塊獨有的內容:
r0_9ir2=0x0
mec_kdbh9ir2=0x37
76543210
shcf_kdbh9ir2=----------
76543210
flag_9ir2=--R---OC
fcls_9ir2[30]={ 0 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 32768 }
perm_9ir2[51]={ 27 50 26 44 0 1 39 42 40 28 43 41 2 3 4 29 30 5 6 48 45 31 32 33 46 34 35 7 8 9 10 49 47 11 12 13 14 15 16 36 37 17 18 19 20 38 21 22 23 24 25 }
0x86:pti[0] nrow=144 offs=0
0x8a:pti[1] nrow=240 offs=144
0x8e:pri[0] offs=0x1b21
…
block_row_dump:
tab 0, row 141, @0x1ea2 -- tab0 字典表
tl: 10 fb: --H-FL-- lb: 0x0 cc: 1
col 0: [ 7] 78 6e 03 15 12 0f 29
bindmp: 00 02 cf 78 6e 03 15 12 0f 29 -- bindmp,原始資料匯出,真正儲存的是這個
…
tab 1, row 0, @0x1a50 --tab1 資料表
tl: 22 fb: --H-FL-- lb: 0x0 cc: 51 --壓縮後行的大小是22
-- 以下col都是恢復(解壓縮)出來的內容
col 0: *NULL*
col 1: [ 5] 56 41 4c 49 44
col 2: [ 2] c1 02
col 3: [ 6] c5 16 30 31 25 2e
col 4: *NULL*
col 5: [ 3] 59 45 53
col 6: [ 1] 4e
col 7: [10] 20 20 20 20 20 20 20 20 20 31
col 8: [10] 20 20 20 20 20 20 20 20 20 31
col 9: [ 5] 20 20 20 20 4e
…
col 50: [10] 54 59 50 45 5f 4d 49 53 43 24
-- 以下是行實際儲存資料
bindmp: 2c 00 06 1d 03 ca c1 2f 44 6b 6b d2 54 59 50 45 5f 4d 49 53 43 24
SQL> select count(*) from t;
COUNT(*)
----------
3002
執行計劃
----------------------------------------------------------
Plan hash value: 2966233522
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 6 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T | 3002 | 6 (0)| 00:00:01 |
-------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement
統計資訊
----------------------------------------------------------
0 recursive calls
0 db block gets
15 consistent gets
0 physical reads
0 redo size
420 bytes sent via SQL*Net to client
416 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
由於表資料進行了壓縮,資料塊大小由96降為16,全表掃描的Cost也由30降到了6,。
Ok,既然資料已經進行了壓縮,那麼,我們在這個已經壓縮的表上再次正常insert資料,看看會不會壓縮?
SQL> insert into t select * from dba_tables;
已建立3003行。
SQL> commit;
提交完成。
SQL> select segment_name,blocks from dba_segments where segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS
----------
T
112
SQL> alter system dump datafile 4 block 555;
系統已更改。
data_block_dump,data header at 0x2056c064
===============
tsiz: 0x1f98
hsiz: 0x5a
pbl: 0x2056c064
76543210
flag=-------- -- 不是壓縮塊
ntab=1
nrow=36
frre=-1
fsbo=0x5a
fseo=0xac
avsp=0x52
tosp=0x52
0xe:pti[0] nrow=36 offs=0
0x12:pri[0] offs=0x1b55
…
block_row_dump:
即使表中已存在的內容是壓縮的,後續未採用直接路徑insert的資料依然不能壓縮。
SQL> conn test/test
已連線。
SQL> drop table t;
表已刪除。
SQL> create table t compress as select * from dba_tables;
表已建立。
SQL> select segment_name,blocks from dba_segments where segment_name='T';
SEGMENT_NAME
--------------------------------------------------------------------------------
BLOCKS
----------
T
16
CTAS可以壓縮表資料。
綜上,對於壓縮表而言,使用範圍要比壓縮索引小的多,僅僅適用於CTAS或直接路徑載入插入。
並且,一般而言,壓縮表由於降低了表的Block數量,直接降低了邏輯讀,雖然壓縮、解壓縮過程會使用額外的CPU資源,但往往是利大於弊。個人認為,對於系統中常用的碼錶(不容易修改,並且資料量不會太大)壓縮可以作為降低資源使用的一種方法。
值得注意的是,對於exp/imp而言,因為無法做直接路徑載入,將會導致壓縮表在匯出、匯入後以正常表來進行儲存。
關於更深入的瞭解壓縮塊的格式,老熊有個很好的文章,請移步
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/19423/viewspace-1032602/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 從底向上瞭解DML操作
- 從底向上第三篇--瞭解index的compressIndex
- 初步瞭解表單操作
- Hbase無法建立帶有snappy壓縮屬性的表APP
- 字串的壓縮和解壓縮字串
- Redis底層資料結構——壓縮列表Redis資料結構
- 瞭解下C# 屬性(Property)C#
- 簡單的zip壓縮和解壓縮
- Nginx網路壓縮 CSS壓縮 圖片壓縮 JSON壓縮NginxCSSJSON
- JAVA壓縮和解壓縮Java
- zip壓縮和解壓縮
- 瞭解SQL Server 2008的新壓縮特性SQLServer
- SQL Server中CTE的另一種遞迴方式-從底層向上遞迴SQLServer遞迴
- 從底向上第七篇--超255列表的儲存
- aix 檔案的壓縮與解壓縮AI
- linux壓縮解壓縮Linux
- 檔案壓縮和解壓縮
- linux下的檔案的壓縮和解壓縮Linux
- ppt怎麼壓縮,ppt壓縮的技巧分享
- Linux中檔案的壓縮和解壓縮Linux
- 解包 bzip2 壓縮的壓縮文件(轉)
- linux 高效壓縮工具之xz的壓縮解壓使用Linux
- Linux下常用壓縮格式的壓縮與解壓方法Linux
- JS壓縮方法及批量壓縮JS
- aix 下壓縮與解壓縮AI
- linux壓縮和解壓縮命令Linux
- tar 分卷壓縮&解壓縮命令
- AIX 上壓縮與解壓縮AI
- 重新認識flex縮寫屬性—[flex]Flex
- CSS-彈性佈局3-伸縮屬性CSS
- Oracle壓縮黑科技(二)—壓縮資料的修改Oracle
- AIX下的壓縮測試及所有壓縮命令AI
- tar的打包-壓縮與解壓縮,並解壓到指定的目錄
- linux下壓縮解壓縮命令Linux
- linux壓縮和解壓縮命令整理Linux
- Linux壓縮及解壓縮命令Linux
- linux壓縮和解壓縮命令大全Linux
- Python實現壓縮和解壓縮Python