Tuesday, November 28, 2006

Oracle table compression

Compress your tables

This feature has been introduced in 9i rel 2 and is most useful in a warehouse environment (for fact tables).

How to compress? Simple

SQL> alter table test move compress;

Table altered.

How Oracle implements compression?

Oracle compress data by eliminating duplicate values within a data-block. Any repetitive occurrence of a value in a block is replaced by a symbol entry in a “symbol table” within the data block. So for example deptno=10 is repeated 5 times within a data block, it will be only stored once and rest 4 times a symbol entry will be stored in symbol table.
Its very important to know that every data block is self contained and sufficient to rebuild the uncompressed form of data.

Table compression can significantly reduce disk and buffer cache requirements for database tables while improving query performance. Compressed tables use fewer data blocks on disk, reducing disk space requirements.

Identifying tables to compress:

First create the following function which will get you the extent of compression

create function compression_ratio (tabname varchar2)
return number is — sample percentage
pct number := 0.000099;
blkcnt number := 0; blkcntc number; begin
execute immediate ' create table TEMP$$FOR_TEST pctfree 0
as select * from ' tabname ' where rownum < 1';
while ((pct < 100) and (blkcnt < 1000)) loop
execute immediate 'truncate table TEMP$$FOR_TEST';
execute immediate 'insert into TEMP$$FOR_TEST select *
from ' tabname ' sample block (' pct ',10)';
execute immediate 'select
count(distinct(dbms_rowid.rowid_block_number(rowid)))
from TEMP$$FOR_TEST' into blkcnt;
pct := pct * 10;
end loop;
execute immediate 'alter table TEMP$$FOR_TEST move compress ';
execute immediate 'select
count(distinct(dbms_rowid.rowid_block_number(rowid)))
from TEMP$$FOR_TEST' into blkcntc;
execute immediate 'drop table TEMP$$FOR_TEST';
return (blkcnt/blkcntc);
end;
/


1 declare
2 a number;
3 begin
4 a:=compression_ratio('TEST');
5 dbms_output.put_line(a);
6 end
7 ;
8 /

2.91389728096676737160120845921450151057

PL/SQL procedure successfully completed.


1 select bytes/1024/1024 "Size in MB" from user_segments
2* where segment_name='TEST'
SQL> /

Size in MB
----------
18

SQL> alter table test move compress;

Table altered.

SQL> select bytes/1024/1024 "Size in MB" from user_segments
2 where segment_name='TEST';

Size in MB
----------
6

After compressing the table, you need to rebuild indexes because the rowid's have changed.

Notes:

- This feature can be best utilized in a warehouse environment where there are lot of duplicate values (for fact tables). Infact a larger block size is more efficient, becuase duplicate values will be only stored once within a block.

- This feature has no -ve effect, infact it accelerates the performance of queries accessing large amount of data.

- I suggest you to read the following white paper by Oracle which explains the whole algorithm in details along with industry recognized TPC test cases.

http://www.vldb.org/conf/2003/papers/S28P01.pdf

I wrote the above article after reading the oramag. I suggest you to read the full article on Oracle site

6 comments:

Unknown said...

Kindly suggest a solution for the below mentioned problem

ORA-00600: internal error code, arguments: [6002], [0], [0], [2], [0], [], [], []
Current SQL statement for this session:
INSERT INTO FINANCE.AP_TRHS(ENTITY_ID,YEAR_ID,PERIOD_ID,TRN_TYPE_ID,UPDATE_USER,UPDATE_DATE,TRN_NO,SUPP_ID,TRN_DATE,CREDIT_PERIOD,NARA,DUEDATE,REF_BILL_NO,REF_BILL_DATE,BILL_AMT,AP_AMT,APPLIED_AMT,NET_AP_AMT,AP_STAT,ACC_ID,SUB_ACC_ID,COST_CENT_ID,PROJ_ID,ENTRY_DATE,CONFIRM_FLAG,REVERSED_AMT) VALUES (:ENTITY_ID,:YEAR_ID,:PERIOD_ID,:TRN_TYPE_ID,:UPDATE_USER,:UPDATE_DATE,:TRN_NO,:SUPP_ID,:TRN_DATE,:CREDIT_PERIOD,:NARA,:DUEDATE,:REF_BILL_NO,:REF_BILL_DATE,:BILL_AMT,:AP_AMT,:APPLIED_AMT,:NET_AP_AMT,:AP_STAT,:ACC_ID,:SUB_ACC_ID,:COST_CENT_ID,:PROJ_ID,:ENTRY_DATE,:CONFIRM_FLAG,:REVERSED_AMT)

Sachin said...

This looks like interna error.
Kindly raise an iTAR with Oracle support.

Also check out Metalink Note: 47449.1

This looks like Index corruption.
If you have indexes on this table. Drop and recreate them OR rebuild them.

Sachin

Unknown said...

i found it very interesting. We have oracle enterprise edition and the commands do work and see a very good difference. Was just wondering,

Would we need additional licensing or need to pay extra or would it be all inclusive in our current purchase.

sandip roy said...

Very good one ...

Unknown said...

Exellent documentation

Mukesh said...

A good article and Really a good reference