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