Thursday, May 6, 2010

11G new feature - Advanced Table Compression

Oracle Database 11g Table Compression allows data to be compressed during all types of data manipulation operations, including conventional DML such as INSERT and UPDATE.
Below operations are candidate for such type of compression:
  1. Direct path SQL*Loader
  2. CREATE TABLE and AS SELECT statements
  3. Parallel INSERT (or serial INSERT with an APPEND hint) statements
  4. Single-row or array inserts
  5. Single-row or array updates
You can convert existing not compressed data to compressed using ALTER TABLE .. MOVE statement.
Now, lets create 2 tables - compressed and and compressed and compare their size:
SQL> create table myt1 as select * from dba_objects;

Table created.

SQL> create table myt2 compress for all operations as select * from dba_objects;
Table created.

SQL> select segment_name, bytes from dba_segments where segment_name in ('MYT1', 'MYT2');

SEGMENT_NAME              BYTES
-------------------- ----------
MYT1                    9437184
MYT2                    3145728
As you see, compressed table is ~3 times smaller.
SQL> alter table myt1 move;

Table altered.

SQL> alter table myt2 move;

Table altered.

SQL> select segment_name, bytes from dba_segments where segment_name in ('MYT1', 'MYT2');

SEGMENT_NAME              BYTES
-------------------- ----------
MYT1                    9437184
MYT2                    3145728

As you see, no difference after normal move statement. Now, lets try moving with compressing option:
SQL> alter table myt1 compress for all operations move;

Table altered.

SQL> select segment_name, bytes from dba_segments where segment_name in ('MYT1', 'MYT2');

SEGMENT_NAME              BYTES
-------------------- ----------
MYT1                    3145728
MYT2                    3145728

That is: now their size is the same. Even after inserting new records size will be same for both of them:
SQL> insert into myt1 select * from myt1;

72046 rows created.

SQL> insert into myt2 select * from myt2;

72047 rows created.

SQL> commit;

Commit complete.

SQL>  select segment_name, bytes from dba_segments where segment_name in ('MYT1', 'MYT2');

SEGMENT_NAME              BYTES
-------------------- ----------
MYT1                   11534336
MYT2                   11534336
All DML operations on comressed table is fast as on normal table. However you may see delay in update statements during heavy updates.
Just for testing, convert myt1 back to not compressed mode.
SQL>  alter table myt1 nocompress move;

Table altered.

SQL> select segment_name, bytes from dba_segments where segment_name in ('MYT1', 'MYT2');

SEGMENT_NAME              BYTES
-------------------- ----------
MYT1                   17825792
MYT2                   11534336

SQL> set timing on
SQL> update myt1 set object_id=1;

144092 rows updated.

Elapsed: 00:00:10.36
SQL> update myt2 set object_id=1;

144094 rows updated.

Elapsed: 00:00:33.72
SQL>

No comments: