不管表是否處於nologging下,direct insert 都不會對數據產生 UNDO

從理論上來說,對於 direct insert 的 undo (rowid)實在沒有存在的必要
因爲HWM 在移動的過程中,這些block是不能被其他process使用的,那麼,意味着,只要記錄下該次direct insert所涉及到的 空間的redo 和 undo  ,在失敗回滾的時候,只需要把這些空間修改爲原來的狀態就可以而而不用逐個記錄去delete。

爲此我將在這裏做幾個組合實驗

SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 - Prod
PL/SQL Release 10.1.0.2.0 - Production
CORE    10.1.0.2.0      Production
TNS for Linux: Version 10.1.0.2.0 - Production
NLSRTL Version 10.1.0.2.0 - Production

SQL>
SQL> drop table t;

Table dropped.

SQL> create table t as select * from dba_objects ;

Table created.

SQL> select usn,RSSIZE ,WRITES from  v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     253952   11168864
         2    2220032   11335220
         3    2220032    9668346
         4    1171456    8887572
         5     122880      84154
         6     122880          0
         7    1171456        234
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> insert into  t select * from dba_objects;

13197 rows created.

SQL> commit;

Commit complete.

SQL> select usn,RSSIZE ,WRITES from  v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     253952   11168864
         2    2220032   11336024
         3    2220032    9668346
         4    2220032    9810066
         5     122880      85452
         6     122880          0
         7    1171456        234
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select 9810066 - 8887572 from dual;

9810066-8887572
---------------
         922494      正常情況下產生的回滾段信息量
SQL> select 85452 - 84152 from dual;

85452-84152
-----------
       1300       undo中這個細微變化目前不詳,估計可能是空間的變化導致的


SQL> alter table t nologging;設置表爲nologging

Table altered.

SQL> insert /*+ append */ into t select * from dba_objects;    direct  insert

13197 rows created.

SQL> commit;

Commit complete.

SQL> select usn,RSSIZE ,WRITES from  v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     253952   11169498
         2    2220032   11339548
         3    2220032    9670376
         4    2220032    9813076
         5     122880      85452
         6     122880          0
         7    1171456        234
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select 9670376 - 9668346 from dual;

9670376-9668346
---------------
           2030 發現回滾段信息極少

SQL> select 9813076-9810066 from dual;

9813076-9810066
---------------
           3010

SQL>






SQL> alter table t logging;   把表置回logging狀態

Table altered.

SQL> select usn,RSSIZE ,WRITES from  v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     253952   11173844
         2    2220032   11343052
         3    2220032    9676700
         4    2220032    9816500
         5     122880      89668
         6     122880          0
         7    1171456        234
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> insert into t select * from dba_objects;  正常插入數據

13197 rows created.

SQL> commit;

Commit complete.

SQL> select usn,RSSIZE ,WRITES from  v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     253952   11173844
         2    2220032   12266342
         3    2220032    9676918
         4    2220032    9817356
         5     122880      90478
         6     122880          0
         7    1171456        234
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select 12266342 - 11343052 from dual;

12266342-11343052
-----------------
           923290    產生的回滾段信息

SQL> insert /*+ append */ into t select * from dba_objects;   direct  insert

13197 rows created.

SQL> commit;

Commit complete.

SQL> select usn,RSSIZE ,WRITES from  v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     253952   11174528
         2    2220032   12266768
         3    2220032    9678420
         4    2220032    9817356
         5     122880      92562
         6     122880          0
         7    1171456        234
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL>

SQL> select  11174528 - 11173844 from dual;

11174528-11173844
-----------------
              684

SQL> select  92562 - 90478 from dual;

92562-90478
-----------
       2084

SQL>
在這裏我們覈對任意一個回滾段的生成量,發現幾乎很少

由此我們幾乎可以下個結論,不管表是否在nologging 下,只要是 direct  insert,就不會對數據內容生成undo,也就是不會爲insert而記錄 rowid






接下來我們進一步實驗,在表同樣處於 logging 狀態下測試

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  133173584 1236385760

SQL> insert into t select * from dba_objects;

13197 rows created.

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  137974492 1236385760

SQL> select  137974492 - 133173584 from dual;

137974492-133173584
-------------------
            4800908  正常插入產生的日誌

SQL> roll;
Rollback complete.
SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  140087680 1236385760

SQL> select 140087680 - 137974492 from dual;

140087680-137974492
-------------------
            2113188  正常插入後回滾所產生的日誌

SQL> insert /*+ append */ into t select * from dba_objects;

13197 rows created.

SQL>  select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  141531644 1236385760

SQL> select 141531644 - 140087680 from dual;

141531644-140087680
-------------------
            1443964   direct 插入產生的日誌

SQL> roll;
Rollback complete.
SQL>  select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  141534344 1236385760

SQL> select 141534344 - 141531644 from dual;

141534344-141531644
-------------------
               2700   direct插入後回滾產生的日誌

SQL>

從這裏的實驗可以看出,在 direct insert 後回滾數據,實際上並沒有進行數據的 刪除操作
而是僅僅對空間進行了回收。若是刪除,不可能只產生這麼少的 redo,這裏從另一個側面證明
即使 logging 下的 direct insert 對於回滾信息,也是不會對數據產生 undo 而僅僅產生空間變化的 undo

 

帶索引表,表和索引均是logging狀態,測試結果及過程如下

----------------------------常規插入-------direct插入      
                  
插入日誌生成量----------------8350864--------2364484

插入回滾段生成量--------------2343894--------426838

回滾日誌生成量----------------4018204--------76032

回滾本身不存在產生回滾-------------------------------------


結論是很顯然的,也許這裏有人要問,既然direct有這麼多好處,那爲什麼還用常規?
因爲920前的版本sqlldr direct導致trigger無用、函數無用
direct直接在hwm上移動而不使用delete刪除釋放的空間可能導致空間浪費
direct的時候,據說同一個extent只能由一個進程使用(未測試,目前無LMT表空間環境)
direct insert 未提交會阻塞其他dml,也會阻止進程自己對該表的查詢。

direct +  nologging 由於不產生數據日誌導致恢復會出現問題

SQL> truncate table t;

Table truncated.

SQL> create index t_index on t(object_id);

Index created.

SQL> col name format a20
SQL> select usn,RSSIZE ,WRITES from v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     516096   14166140
         2    1171456   17003930
         3    2220032   13918700
         4    1171456   13550540
         5     122880     756246
         6     122880          0
         7    1171456        312
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  181757168 1236385760

SQL> insert into t select * from dba_objects;

13198 rows created.

SQL> select usn,RSSIZE ,WRITES from v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     516096   14166140
         2    4317184   19347824
         3    2220032   13918700
         4    1171456   13551396
         5     122880     756246
         6     122880          0
         7    1171456        312
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  190108032 1236385760

SQL> select 19347824 - 17003930 from dual;

19347824-17003930
-----------------
          2343894   存在索引,常規插入方式下產生的回滾量

SQL> select 190108032 - 181757168 from dual;

190108032-181757168
-------------------
            8350864 存在索引,常規插入方式下產生的日誌量

SQL> roll;
Rollback complete.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     516096   14166140
         2    4317184   19347824
         3    2220032   13918700
         4    1171456   13551396
         5     122880     757102
         6     122880          0
         7    1171456        312
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  194126236 1236385760

SQL> select 194126236 - 190108032 from dual;

194126236-190108032
-------------------
            4018204   存在索引,常規插入方式下然後回滾所產生的日誌量

SQL> truncate table t;

Table truncated.

SQL> select usn,RSSIZE ,WRITES from v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1     581632   14185742
         2    4317184   19356862
         3    2220032   13936438
         4    1171456   13566936
         5     122880     757102
         6     122880          0
         7    1171456        312
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  194287336 1236385760

SQL> insert /*+ append */ into t select * from dba_objects;

13198 rows created.

SQL> select usn,RSSIZE ,WRITES from v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1    2088960   14612580
         2    4317184   19356862
         3    2220032   13936438
         4    1171456   13569090
         5     122880     757102
         6     122880          0
         7    1171456        312
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  196651820 1236385760

SQL> select 14612580 - 14185742 from dual;

14612580-14185742
-----------------
           426838    存在索引,direct插入方式下產生的回滾量

SQL> select 196651820 - 194287336 from dual;

196651820-194287336
-------------------
            2364484  存在索引,direct插入方式下產生的日誌量

SQL> roll;
Rollback complete.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;

       USN     RSSIZE     WRITES
---------- ---------- ----------
         0     385024       7620
         1    2088960   14612580
         2    4317184   19360722
         3    2220032   13936438
         4    1171456   13569946
         5     122880     757908
         6     122880          0
         7    1171456        312
         8     122880          0
         9     122880          0
        10     122880          0

11 rows selected.

SQL> select * from v$sysstat where name = 'redo size';

STATISTIC# NAME                      CLASS      VALUE    STAT_ID
---------- -------------------- ---------- ---------- ----------
       133 redo size                     2  196727852 1236385760

SQL> select  196727852 - 196651820 from dual;

196727852-196651820
-------------------
              76032  存在索引,direct插入方式下回滾產生的日誌量

SQL>


 

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