Heute wurde im OTN Forum die Frage diskutiert, ob dbms_compression.get_compression_ratio für bereits komprimierte Tabellen eine Aussage zur Effektivität der Komprimierung liefert: also ob sich durch Updates so viele Entpackungen von Datensätzen ergeben haben, dass eine erneute Komprimierung sinnvoll wäre. Ich habe zur Beantwortung mein Standardverfahren eingesetzt:
- Nachdenken
- Zu keinem eindeutigen Ergebnis kommen
- Test erstellen und ausprobieren
Der Test in 11.2.0.1 dazu sah etwa folgendermaßen aus - und bediente sich aus ähnlichen Beispielen von Christian Antognini und Neil Johnson (die, hätte ich sie sorgfältig gelesen, die im Raum stehende Frage bereits beantwortet hätten):
-- Test mit einem User mit DBA-Rechten -- Anlage eines Tablespace für temporäre Testobjekte create tablespace scratch datafile 'E:\ORACLE_DATA\TEST\SCRATCH.DBF' size 50M; -- Anlage einer Test-Tabelle drop table t; create table t as select rownum id , lpad('*', 50, '*') compressable_col from dual connect by level <= 1000000; exec dbms_stats.gather_table_stats(user, 'T') -- Aufruf der Prozedur zur Bestimmung der Komprimierungseffekte DECLARE l_blkcnt_cmp BINARY_INTEGER; l_blkcnt_uncmp BINARY_INTEGER; l_row_cmp BINARY_INTEGER; l_row_uncmp BINARY_INTEGER; l_cmp_ratio NUMBER; l_comptype_str VARCHAR2(100); BEGIN dbms_compression.get_compression_ratio( -- input parameters scratchtbsname => 'SCRATCH', -- scratch tablespace ownname => user, -- owner of the table tabname => 'T', -- table name partname => NULL, -- partition name comptype => dbms_compression.comp_for_oltp, -- compression algorithm subset_numrows => 1000000, -- output parameters blkcnt_cmp => l_blkcnt_cmp, -- number of compressed blocks blkcnt_uncmp => l_blkcnt_uncmp, -- number of uncompressed blocks row_cmp => l_row_cmp, -- number of rows in a compressed block row_uncmp => l_row_uncmp, -- number of rows in an uncompressed block cmp_ratio => l_cmp_ratio, -- compression ratio comptype_str => l_comptype_str -- compression type ); dbms_output.put_line('type: '|| l_comptype_str); dbms_output.put_line('blocks comp: '|| l_blkcnt_cmp); dbms_output.put_line('blocks uncomp: '|| l_blkcnt_uncmp); dbms_output.put_line('ratio: '|| to_char(l_cmp_ratio,'99.999')); END; / type: "Compress For OLTP" blocks comp: 203 blocks uncomp: 1024 ratio: 5.000 select blocks from dba_segments where segment_name = 'T'; BLOCKS ---------- 9216
Die "blocks uncomp" haben also nichts mit der tatsächlichen Größe des Basisobjekts zu tun - und bereits die erforderliche Angabe des "scratchtbsname" konnte vermuten lassen, dass hier temporäre Objekte und Sampling im Spiel sind. Diese Annahme bestätigt dann auch das zugehörige SQL-Trace:
create table "TEST".DBMS_TABCOMP_TEMP_UNCMP tablespace "SCRATCH" nologging as select /*+ FULL("TEST"."T") */ * from "TEST"."T" sample block( 22) mytab create table "TEST".DBMS_TABCOMP_TEMP_CMP organization heap tablespace "SCRATCH" compress for oltp nologging as select /*+ FULL("TEST"."T") */ * from "TEST".DBMS_TABCOMP_TEMP_UNCMP mytab
Hier wird also via CTAS eine nicht komprimierte Tabelle aus einem Sample des Quellobjekts erzeugt und zu diesem Sample wird dann anschließend eine komprimierte Version angelegt. Ungefähr so hätte ich das wahrscheinlich auch gemacht, wenn ich einen entsprechenden Test manuell durchgeführt hätte. Zur Beantwortung der ursprünglichen Frage könnte die Procedure demnach nur indirekt dienen.
Keine Kommentare:
Kommentar veröffentlichen