表圧縮は2種類あります
圧縮といっても正確には「重複値排除」のようです。1ブロック内に格納されるレコードに同一列値があると省略されるイメージです。当然圧縮,非圧縮にはCPUコストがかかるわけですが、サイズが小さくなる分DiskI/Oのコストを下げてトータルパフォーマンスを良くする狙いがあるようです。 実際に業務へ適用するにはいろいろ検証が必要とはなりますが使い処によってはかなり有効な機能です。ここでは簡単な利用方法を紹介します。(圧縮した表に対して列の追加や削除はできません。いったん元に戻してから行う事になります)
create tableで圧縮方法を指定し作成しておけばデータをinsertするタイミングで圧縮してくれますし、既存のテーブルに対し、alter table文で後から圧縮する事もできます。何れもブロック単位での圧縮となるようです。但し圧縮方法によっては以下のような注意点があります。
圧縮方法 | 注意 | CREATE/ALTER TABLEの構文 |
基本表圧縮 | ダイレクト・パス・ロードinsertのみ圧縮される。バッファキャッシュを経由する(通常の)insertでは圧縮されません。(alter table文で後から圧縮するにはこちらの制限はかかりません) | ROW STORE COMPRESS |
OLTP圧縮 |
通常IのNSERTにも対応。ブロック内の閾値に達するまでは非圧縮でINSERETされ、閾値に達すると圧縮が始まる。名前の通りオンラインシステムに採用するのであればこちらでないとほぼ使い物にならないでしょうねぇ、、 有償オプション(Advanced Compression Option) |
ROW STORE COMPRESS ADVANCED (補足参照) |
(補足)COMPRESS FOR OLTP でも同じ意味のようです。こちらは11gまで使われていたようで、上位互換を満たすために12c以降でもそのまま利用できるようです。つまり以下はどちらも同じ意味です。
-- 通常のテーブルをOLTP圧縮します
alter table SOONI.TESTTBL MOVE COMPRESS FOR OLTP
;
alter table SOONI.TESTTBL MOVE ROW STORE COMPRESS ADVANCED
;
基本表圧縮
alter table SOONI.TESTTBL MOVE ROW STORE COMPRESS ;
OLTP圧縮
alter table SOONI.TESTTBL MOVE ROW STORE COMPRESS ADVANCED ;
-- パーティションの圧縮 ALTER TABLE RPEX01 MOVE PARTITION DAY3 ROW STORE COMPRESS ADVANCED ;
NOCOMPRESSへ変更(元に戻す)
どちらの圧縮方法の場合も以下で元に戻せます。参考までにですが、基本圧縮しているテーブルをOLTP圧縮に、その逆も直接alter table文を発行する事で実現できます。
alter table SOONI.TESTTBL MOVE NOCOMPRESS ;
-- パーティションの場合 alter table SOONI.RPEX01 MOVE PARTITION DAY3 NOCOMPRESS ;
圧縮を確認する
dba_tablesのCOMPRESSION、COMPRESS_FORカラムを参照する事で確認できます。以下はdba_segmentsと結合しサイズも確認しています。
select t.OWNER,t.TABLE_NAME,t.TABLESPACE_NAME,t.COMPRESSION,t.COMPRESS_FOR ,s.BYTES/1024/1024 mbyte,s.BLOCKS from dba_segments s inner join dba_tables t on s.OWNER = t.OWNER and s.SEGMENT_NAME=t.TABLE_NAME and s.SEGMENT_TYPE='TABLE' where t.TABLE_NAME like 'TBL%' order by t.TABLE_NAME ;
SQL> set sqlformat ansiconsole
SQL> select t.OWNER,t.TABLE_NAME,t.TABLESPACE_NAME,t.COMPRESSION,t.COMPRESS_FOR,s.BYTES/1024/1024 mbyte,s.BLOCKS
2 from dba_segments s inner join dba_tables t
3 on s.OWNER = t.OWNER and s.SEGMENT_NAME=t.TABLE_NAME and s.SEGMENT_TYPE='TABLE'
4 where t.TABLE_NAME like 'TBL%'
5 order by t.TABLE_NAME
6 ;
OWNER TABLE_NAME TABLESPACE_NAME COMPRESSION COMPRESS_FOR MBYTE BLOCKS
___________ _____________ __________________ ______________ _______________ _________ _________
SOONI TBL16 TBS01 DISABLED 456 58368
SOONI TBL17 TBS01 ENABLED ADVANCED 136 17408
SOONI TBL26 TBS02 ENABLED ADVANCED 104 13312
SOONI TBL27 TBS02 ENABLED BASIC 104 13312
4行が選択されました。
SQL>
テーブルとインデックスの圧縮状況を確認する
select * from ( select s.OWNER,s.SEGMENT_TYPE,s.SEGMENT_NAME,t.TABLESPACE_NAME ,s.BYTES/1024/1024 M_byte,s.BLOCKS,t.COMPRESSION,t.COMPRESS_FOR,t.STATUS from dba_segments s inner join dba_tables t on s.OWNER = t.OWNER and s.SEGMENT_NAME = t.TABLE_NAME and s.SEGMENT_TYPE ='TABLE' union all select s.OWNER,s.SEGMENT_TYPE,s.SEGMENT_NAME,i.TABLESPACE_NAME ,s.BYTES/1024/1024 M_byte,s.BLOCKS,i.COMPRESSION,null as COMPRESS_FOR,i.STATUS from dba_segments s inner join dba_indexes i on s.OWNER = i.OWNER and s.SEGMENT_NAME = i.INDEX_NAME and s.SEGMENT_TYPE ='INDEX' ) x order by x.M_BYTE desc ;