Una din opțiunile mele preferate dar prea puțin explorată pe acest site este Oracle Advanced Compression. Prezentă încă din versiunea 9i și îmbunătățită constant cu fiecare nouă versiune este una dintre cele mai utile opțiuni prin care se pot reduce costurile și crește eficientizarea infrastructurii.
Spațiul alocat unui articol este insuficient chiar și pentru a sumariza potențialul acestei opțiuni, totuși voi începe astăzi printr-un exemplu de compresare a unei tabele și analiza acesteia după micșorarea dimensiunii, urmând ca în articolele viitoare să readuc în discuție acest subiect și să-l completez.
Înainte de a începe testul mai merită menționat că avem la dispoziție șase opțiuni pentru compresia datelor din tabelă din care patru sunt doar pentru Exadata:
- BASIC compression, disponibilă din Oracle 9iR2 recomandat pentru Data Warehouse
- OLTP compression, disponibilă în Oracle 11 și recomandat pentru OLTP
- QUERY LOW compression (Exadata ), recomandat pentru Data Warehouse unde timpul de citire este mai important decât salvarea spațiului
- QUERY HIGH compression (Exadata ), recomandat pentru Data Warehouse unde salvarea spațiului este mai importantă decât timpul de citire
- ARCHIVE LOW compression (Exadata ), recomandat pentru arhivarea datelor unde timpul de citire este mai important decât salvarea spațiului
- ARCHIVE HIGH compression (Exadata ), recomandat pentru arhivarea datelor unde salvarea spațiului este mai importantă decât timpul de citire
Pentru acest exemplu am folosit trei tabele identice pe care le-am generat cu ajutorul următorului query:
select rownum as id, dbms_random.string('X',10) as name, trunc(dbms_random.value(1,1e6)) as amount, trunc(sysdate - 9999 + mod(rownum,10000)) as odate, SYSDATE-1000+DBMS_RANDOM.VALUE(0,1000) as rdate from dual connect by level<=2e6;
Pentru a mă convinge că nu există diferențe verific dimensiunea segmentelor și analizez statisticile pentru fiecare tabelă pentru a compara blocurile :
SQL> analyze table test.no_compress compute statistics; Table analyzed. SQL> analyze table test.basic_compress compute statistics; Table analyzed. SQL> analyze table test.oltp_compress compute statistics; Table analyzed. SQL> select table_name, compression, compress_for, blocks, empty_blocks from dba_tables where owner='TEST'; TABLE_NAME COMPRESS COMPRESS_FOR BLOCKS EMPTY_BLOCKS ------------------------------ -------- --------------- ---------- ------------ BASIC_COMPRESS DISABLED 11917 371 NO_COMPRESS DISABLED 11916 372 OLTP_COMPRESS DISABLED 11917 371 SQL> SELECT segment_name,segment_type,bytes,extents FROM dba_segments where owner='TEST'; SEGMENT_NAME SEGMENT_TYPE BYTES EXTENTS -------------------- ------------------ ---------- ---------- OLTP_COMPRESS TABLE 100663296 83 BASIC_COMPRESS TABLE 100663296 83 NO_COMPRESS TABLE 100663296 83
Definesc tipul de compresie pentru cele două tabele:
SQL> ALTER TABLE test.basic_compress COMPRESS BASIC; Table altered. SQL> ALTER TABLE test.oltp_compress COMPRESS FOR OLTP; Table altered.
Si compresez datele din tabele
SQL> ALTER TABLE test.basic_compress move nologging; Table altered. SQL> ALTER TABLE test.oltp_compress move nologging; Table altered.
Rezultatul este cat se poate de surprinzător:
SQL> analyze table test.basic_compress compute statistics; Table analyzed. SQL> analyze table test.oltp_compress compute statistics; Table analyzed. SQL> select table_name, compression, compress_for, blocks, empty_blocks from dba_tables where owner='TEST'; TABLE_NAME COMPRESS COMPRESS_FOR BLOCKS EMPTY_BLOCKS ------------------------------ -------- --------------- ---------- ------------ OLTP_COMPRESS ENABLED ADVANCED 11917 371 NO_COMPRESS DISABLED 11916 372 BASIC_COMPRESS ENABLED BASIC 10729 535 SQL> SELECT segment_name,segment_type,bytes,extents FROM dba_segments where owner='TEST'; SEGMENT_NAME SEGMENT_TYPE BYTES EXTENTS -------------------- ------------------ ---------- ---------- OLTP_COMPRESS TABLE 100663296 83 BASIC_COMPRESS TABLE 92274688 82 NO_COMPRESS TABLE 100663296 83
Numărul blocurilor goale pentru tabela OLTP_COMPRESS a rămas neschimbat la fel și dimensiunea segmentelor în schimb prin compresarea tabelei BASIC_COMPRESS s-au redus semnificativ numărul blocurilor, de asemenea s-a redus și dimensiunea segmentelor.
Testul de astăzi nu se poate încheia decât după generarea unui full table scan pentru fiecare din cele trei tabele.
SQL> SET AUTOTRACE ON SQL> select max(AMOUNT) from test.no_compress; MAX(AMOUNT) ----------- 999998 Execution Plan ---------------------------------------------------------- Plan hash value: 2367309921 ---------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 3241 (1)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 4 | | | | 2 | TABLE ACCESS FULL| NO_COMPRESS | 2000K| 7812K| 3241 (1)| 00:00:01 | ---------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 29 recursive calls 0 db block gets 11801 consistent gets 11765 physical reads 0 redo size 547 bytes sent via SQL*Net to client 552 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 5 sorts (memory) 0 sorts (disk) 1 rows processed
SQL> select max(AMOUNT) from test.basic_compress; MAX(AMOUNT) ----------- 999999 Execution Plan ---------------------------------------------------------- Plan hash value: 1384053070 ------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | 4 | 2919 (1)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 4 | | | | 2 | TABLE ACCESS FULL| BASIC_COMPRESS | 2000K| 7812K| 2919 (1)| 00:00:01 | ------------------------------------------------------------------------------------- Statistics ---------------------------------------------------------- 1 recursive calls 0 db block gets 10586 consistent gets 10582 physical reads 0 redo size 547 bytes sent via SQL*Net to client 552 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
SQL> select max(AMOUNT) from test.oltp_compress; MAX(AMOUNT) ----------- 999999 Execution Plan ---------------------------------------------------------- Plan hash value: 2657484797 ------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 1 | 4 | 3241 (1)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 4 | | | | 2 | TABLE ACCESS FULL| OLTP_COMPRESS | 2000K| 7812K| 3241 (1)| 00:00:01 | ------------------------------------------------------------------------------------ Statistics ---------------------------------------------------------- 0 recursive calls 0 db block gets 11770 consistent gets 11766 physical reads 0 redo size 547 bytes sent via SQL*Net to client 552 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 1 rows processed
Așa cum era de așteptat prin reducerea blocurilor s-a redus numărul de citiri și a scăzut costul. Dar este foarte probabil ca rezultatul să fie diferit în funcție de versiunea bazei de date și tipul de date din tabele, de aceea recomand să nu considerați testul de astăzi general valabil, dimpotrivă vă sfătuiesc analizați și să explorați într-un mediu controlat toate opțiunile înainte de a fi implementate în producție.