【表壓縮】使用表壓縮技術將表所佔用空間降低到最小

secooler發表於2009-12-06
很多情況下,Oracle預設的表儲存策略並不符合我們使用資料的實際情況。例如,在OLAP型別的系統中,資料的使用方式一般是定期批次初始化大量資料,此後的工作便是查詢、分析和統計,很少的修改動作。基於這樣的使用前提,我們完全有理由將表的使用空間儘量減少,以便節省儲存空間並提高系統的吞吐量。

哪些技術可以降低表的儲存空間呢?
第一種方法是降低PCTFREE的值,因為我們沒有必要為以後的更新留有空間,極端情況下我們也可以將PCTFREE的值設定為0;
第二種方法是表壓縮技術,使用這種技術可以進一步減少表所佔用的空間。

透過實驗我們來展示一下這兩種方法,重點會放在使用表壓縮技術帶給我們的神奇效果。

1.在系統預設的儲存引數下建立表T,該表是藉助ALL_OBJECTS檢視內容生成的,包含一千萬條記錄,共佔用段空間1G。
1)確認記錄條數:一千萬條。
sec@ora10g> select count(*) from t;

  COUNT(*)
----------
  10000000

2)使用DBMS_METADATA.GET_DDL得到T表的全貌,可見預設的PCTFREE值是10。
sec@ora10g> set longchunksize 150
sec@ora10g> select dbms_metadata.get_ddl('TABLE','T','SEC') from dual;

DBMS_METADATA.GET_DDL('TABLE','T','SEC')
-----------------------------------------------------------------------

  CREATE TABLE "SEC"."T"
   (    "X" NUMBER,
        "OWNER" VARCHAR2(30) NOT NULL ENABLE,
        "OBJECT_NAME" VARCHAR2(30) NOT NULL ENABLE,
        "SUBOBJECT_NAME" VARCHAR2(30),
        "OBJECT_ID" NUMBER NOT NULL ENABLE,
        "DATA_OBJECT_ID" NUMBER,
        "OBJECT_TYPE" VARCHAR2(19),
        "CREATED" DATE NOT NULL ENABLE,
        "LAST_DDL_TIME" DATE NOT NULL ENABLE,
        "TIMESTAMP" VARCHAR2(19),
        "STATUS" VARCHAR2(7),
        "TEMPORARY" VARCHAR2(1),
        "GENERATED" VARCHAR2(1),
        "SECONDARY" VARCHAR2(1)
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS NOLOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "TBS_SEC_D"

3)確認表T佔用的段空間大小,我們的目標就是在此基礎上使其佔用的段空間大小盡量的小。
sec@ora10g> select owner,segment_name table_name,segment_type type,bytes/1024/1024 mb from dba_segments where segment_name = 'T';

OWNER     TABLE_NAME     TYPE                         MB
--------- -------------- -------------------- ----------
SEC       T              TABLE                      1088

2.減少儲存空間的第一次嘗試:將PCTFREE的值降為0。
1)為對比方便,我們使用CTAS方法建立表T_PCTFREE0
sec@ora10g> create table t_pctfree0 pctfree 0 as select * from t;

Table created.

2)檢視一下空間的節省情況,大約節省了原T表所佔空間的10%。
sec@ora10g> select owner,segment_name table_name,segment_type type,bytes/1024/1024 mb from dba_segments where segment_name = 'T_PCTFREE0';

OWNER     TABLE_NAME     TYPE                         MB
--------- -------------- -------------------- ----------
SEC       T_PCTFREE0     TABLE                       960

3.減少儲存空間的第二次嘗試:使用表壓縮技術。
1)使用“compress”選項建立具有表壓縮特性的表T_COMPRESS
sec@ora10g> create table t_compress compress as select * from t;

Table created.

2)檢視一下空間的節省情況,此時大約節省了原T表所佔空間的65%,效果驚人。
sec@ora10g> select owner,segment_name table_name,segment_type type,bytes/1024/1024 mb from dba_segments where segment_name = 'T_COMPRESS';

OWNER     TABLE_NAME     TYPE                         MB
--------- -------------- -------------------- ----------
SEC       T_COMPRESS     TABLE                       376

3)使用表壓縮技術建立的表本身就具有PCTFREE為“0”的性質。
sec@ora10g> select dbms_metadata.get_ddl('TABLE','T_COMPRESS','SEC') from dual;

DBMS_METADATA.GET_DDL('TABLE','T_COMPRESS','SEC')
----------------------------------------------------------------------

  CREATE TABLE "SEC"."T_COMPRESS"
   (    "X" NUMBER,
        "OWNER" VARCHAR2(30) NOT NULL ENABLE,
        "OBJECT_NAME" VARCHAR2(30) NOT NULL ENABLE,
        "SUBOBJECT_NAME" VARCHAR2(30),
        "OBJECT_ID" NUMBER NOT NULL ENABLE,
        "DATA_OBJECT_ID" NUMBER,
        "OBJECT_TYPE" VARCHAR2(19),
        "CREATED" DATE NOT NULL ENABLE,
        "LAST_DDL_TIME" DATE NOT NULL ENABLE,
        "TIMESTAMP" VARCHAR2(19),
        "STATUS" VARCHAR2(7),
        "TEMPORARY" VARCHAR2(1),
        "GENERATED" VARCHAR2(1),
        "SECONDARY" VARCHAR2(1)
   ) PCTFREE 0 PCTUSED 40 INITRANS 1 MAXTRANS 255 COMPRESS LOGGING
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "TBS_SEC_D"

4.減少儲存空間的第三次嘗試:“使用表壓縮技術” + “選取最佳排序欄位”。
表壓縮技術從原理上講,是透過將資料塊中重複資料抽取成為符號表的方法來實現的,因此,如果我們有辦法將儲存在每一塊上儲存的重複資料儘量多,便可以進一步的減少表所佔用空間大小。我們可以使用order by對原表中重複度較大的欄位進行排序的方法達到這個目的。
1)針對表T我們知道,在owner, object_type, object_name欄位上存在大量的重複資訊,因此我們對其進行排序後再建立壓縮表T_COMPRESS_ORDER。
sec@ora10g> create table t_compress_order compress as select * from t order by owner, object_type, object_name;

Table created.

2)檢視一下空間的節省情況,此時大約節省了原T表所佔空間的88%,原1G的表現在僅為136M,真是歎為觀止!
sec@ora10g> select owner,segment_name table_name,segment_type type,bytes/1024/1024 mb from dba_segments where segment_name = 'T_COMPRESS_ORDER';

OWNER     TABLE_NAME       TYPE                         MB
--------- ---------------- -------------------- ----------
SEC       T_COMPRESS_ORDER TABLE                       136

5.一味的減少表的儲存空間是不可取的
有利必有弊,雖然我們上面透過對“owner, object_type, object_name”三個欄位排序後得到了一個非常好的壓縮效果。不過在某些檢索條件下該表並沒有優勢,例如我們使用非排序欄位作為where子句中的條件進行查詢時,查詢效率會大打折扣。

6.表壓縮技術適用場合
如果是OLTP系統,這個技術是非常不合適的,原因不言自明(PCTFREE是0;OLTP增刪改查活動頻繁);
非常適合以查詢為主(或只讀)的靜態資料表;
多見於資料倉儲系統。

7.小結
表壓縮技術在降低表的儲存空間方面功不可沒。降低了表的儲存空間一方面可以節省大量寶貴的儲存資源,同時也可以提升系統的整體效能(需讀取的資料塊數大大減少)。不過表壓縮技術本身具有的限制亦不容忽視,使用前需要做好充分的測試。

Good luck.

secooler
09.12.06

-- The End --

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/519536/viewspace-621766/,如需轉載,請註明出處,否則將追究法律責任。

相關文章