Oracle11新特性——在線操作功能增強之表增加包含默認值的字段

在11g以前,當表很大的時候,如果往表中新增一個NOT NULL的字段,不光是執行速度慢,而且由於現有數據長度的變化,很容易造成表中大量的行鏈接情況,進而使表佔用的空間大大增加。
在11g中,這種情況得到了徹底的改善,Oracle通過在數據字典中記錄DEFAULT值,避免了繁重的更新操作,增加非空字段的時間和增加一個可空字段的時間完全一樣。

10g中添加一個包含DEFAULT值的非空字段的測試:

 

Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.4.0
Connected as ppsclient


SQL> select count(1) from yu_test1;

  COUNT(1)
----------
     31956

SQL>
SQL> Select owner, Segment_Name, Sum(bytes) / 1024 DSIZE
  2    From DBA_Extents
  3   where Segment_Name = 'YU_TEST1'
  4   Group By owner, Segment_Name
  5   order by 3 desc;

OWNER                          SEGMENT_NAME                                                                          DSIZE
------------------------------ -------------------------------------------------------------------------------- ----------
PPSCLIENT                      YU_TEST1                                                                               3072

SQL>

 

SQL> ALTER TABLE YU_TEST1 ADD NEW_COL CHAR(1000) DEFAULT 'TEST COLUMN' NOT NULL;

Table altered

耗時:4.12s

SQL>
SQL> Select owner, Segment_Name, Sum(bytes) / 1024 DSIZE
  2    From DBA_Extents
  3   where Segment_Name = 'YU_TEST1'
  4   Group By owner, Segment_Name
  5   order by 3 desc;

OWNER                          SEGMENT_NAME                                                                          DSIZE
------------------------------ -------------------------------------------------------------------------------- ----------
PPSCLIENT                      YU_TEST1                                                                              44032

 

 

11g中添加一個包含DEFAULT值的非空字段的測試:

 

 

Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as SYS
 
SQL> select count(1) from yuzh.yu_test1;
 
  COUNT(1)
----------
     31956
 
SQL>
SQL> Select owner, Segment_Name, Sum(bytes) / 1024 DSIZE
  2    From DBA_Extents
  3   where Segment_Name = 'YU_TEST1'
  4   Group By owner, Segment_Name
  5   order by 3 desc;
 
OWNER                          SEGMENT_NAME                                                                          DSIZE
------------------------------ -------------------------------------------------------------------------------- ----------
YUZH                           YU_TEST1                                                                               3072
  
SQL>  ALTER TABLE yuzh.YU_TEST1 ADD NEW_COL CHAR(1000) DEFAULT 'TEST COLUMN' NOT NULL;
 
Table altered
 

耗時:0.89s


SQL>
SQL> Select owner, Segment_Name, Sum(bytes) / 1024 DSIZE
  2    From DBA_Extents
  3   where Segment_Name = 'YU_TEST1'
  4   Group By owner, Segment_Name
  5   order by 3 desc;
 
OWNER                          SEGMENT_NAME                                                                          DSIZE
------------------------------ -------------------------------------------------------------------------------- ----------
YUZH                           YU_TEST1                                                                               3072
 
SQL>

 

 

從上面的測試可以看出,雖然只有3萬的數據,但是10g添加字段用了4秒,而11g只用了不到1s,而且不光是時間上快了很多,空間上夜節省了很多,10新增字段後差不多要44m,而11g增加後還是隻有3m。再來的優點還有就是生成REDO和UNDO的大小,11g也遠小於10g的,這方面的測試不做了。

這裏又出現了個問題,爲什麼11g新增字段後表大小沒有變化呢,說起來也很簡單。Oracle11g中,在添加一個包含DEFAULT值的NOT NULL字段,Oracle不會去更新現有的數據,Oracle需要做的不過是將默認值以及對應的表信息、列信息一起存儲在一個新增數據字典表ecol$中。這張表利用BLOB字段存儲ALTER TABLE添加的DEFAULT值:

 

SQL> SELECT OBJECT_ID FROM DBA_OBJECTS WHERE OBJECT_NAME = 'YU_TEST1';
 
 OBJECT_ID
----------
     73202
 
SQL> SELECT * FROM SYS.ECOL$ WHERE TABOBJ# = 73202;
 
   TABOBJ#     COLNUM BINARYDEFVAL
---------- ---------- ------------
     73202          6 <BLOB>

 

Oracle在讀取數據時,發現COLUMN 6列爲非空,但是在存儲的數據中找不到該列,於是就會從ECOL$中讀取該列的默認值。
這個功能不但提高了添加非空字段的速度,而且節省了大量的磁盤空間。相比之下,在數據字典中查找DEFAULT VALUE的代價小的幾乎可以忽略。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章