Oracle DML NOLOGGING

bfc99發表於2014-07-03
以下轉自:http://blog.csdn.net/tianlesoftware/article/details/5701596 作者:Dave
 

一. NOLOGGING 說明

在對大表插入資料的時候,經常會用到nologging 選項。Nologging 並不是不產生redonologging  +  direct 只是不會對資料產生 redo(但依然有其他的redo

同理 logging +  direct 下 undo 也是大大地減少, 減少的是 資料的undo 這裡強調的是 資料本身的undo ,就如同 redo的減少也一樣,是 資料本身的 redo ,這和資料庫是否產生  redo 和 undo 是不同的概念,比如空間分配的 redo and undo ,這就不是資料本身的變化

 

 

非歸檔模式下, 對於nologging 和 logging模式,只有使用 append,才不會對資料生成redo。 

在歸檔模式下,只有將表置於nologging 模式,並且使用append 才不會對資料生成redo. 

 



二. 歸檔模式下的示例

兩個查詢用的指令碼
--new.sql
column OLD_VALUE new_value OLD_VALUE
select value OLD_VALUE
from v$mystat, v$statname
where v$mystat.statistic# = v$statname.statistic#
and v$statname.name = 'redo size';

--diff.sql
select (value - &OLD_VALUE) OLD_VALUE
from v$mystat, v$statname
where v$mystat.statistic# = v$statname.statistic#
and v$statname.name = 'redo size';

 

資料庫執行在歸檔模式
SQL> archive log list

資料庫日誌模式            存檔模式

自動存檔             啟用

存檔終點            d:/archivelog

最早的聯機日誌序列     125

下一個存檔日誌序列   127

當前日誌序列           127



2.1  Create TABLE

SQL> @?/new.sql

 OLD_VALUE

----------

   8535492
SQL> create table T_NOLOG nologging as select * from all_objects;

表已建立。
SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -    8535492) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

     83496

注:REDO SIZE=83496


SQL> @?/new.sql

 OLD_VALUE

----------

   8618988

SQL> create table T_LOG logging as select * from all_objects;

表已建立。
SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -    8618988) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8491836

注:REDO SIZE=8491836

總結:通過上面的2個例子,可以看出用nologging 建立表,不會對資料生成redo,僅對資料字典生成redo. 

      create table with nologging... not generate redo, just generate for data dictionary 


2.2  DELETE

SQL> @?/new.sql

 OLD_VALUE

----------

  17110824
SQL> DELETE FROM T_NOLOG;

已刪除71711行。
SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   17110824) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  26592364

注:REDO SIZE=26592364


SQL> @?/new.sql

 OLD_VALUE

----------

  43703188

SQL> DELETE FROM T_LOG;

 

已刪除71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   43703188) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  26592560


注:REDO SIZE=26592560


2.3 INSERT

SQL> @?/new.sql

 OLD_VALUE

----------

  70295748

SQL> INSERT INTO T_NOLOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   70295748) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8169900


注:REDO SIZE=8169900


SQL> @?/new.sql

 OLD_VALUE

----------

  78465648

SQL> INSERT INTO T_LOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   78465648) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8169796


注:REDO SIZE=8169796


2.4  UPDATE

SQL> @?/new.sql

 OLD_VALUE

----------

  86635444

SQL> UPDATE T_NOLOG  SET OBJECT_ID=1;

已更新71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   86635444) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  24323896


注:REDO SIZE=24323896


SQL> @?/new.sql

 OLD_VALUE

----------

 110959340

SQL> UPDATE T_LOG SET OBJECT_ID=1;

已更新71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  110959340) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  36490988


注:REDO SIZE=20911424

總結: insert/update/delete DML 操作,在loggingnologging上沒有區別
   On DML insert/update/delete redo size with nologging not difference... with logging. 


2.5  Show case "APPEND" hints

2.5.1  table NOLOGGING and not use APPEND hints 

SQL> @?/new.sql

 OLD_VALUE

----------

 147450328

SQL> INSERT INTO T_NOLOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  147450328) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8325816

注: REDO SIZE=8325816

SQL> @?/new.sql

 OLD_VALUE

----------

 155776144

SQL>  INSERT /*+ APPEND */ INTO T_NOLOG  SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  155776144) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

     14852


注:REDO SIZE=14852,採用append後,redo size大幅減小



2.5.2  table LOGGING, and use APPEND hints 

SQL> @?/new.sql

 OLD_VALUE

----------

 155790996

SQL>  INSERT /*+ APPEND */ INTO T_LOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  155790996) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8406068


注:REDO SIZE=8640396 redo size 沒什麼變化

將表改為nologging 模式,在檢視 


SQL> @?/new.sql

 OLD_VALUE

----------

 164200200

SQL>  INSERT /*+ APPEND */ INTO T_LOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  164200200) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

     15012

注:REDO SIZE=27956

總結: 通過實驗看出,

對於logging 模式, 使用append hint 在生成redo 上沒有什麼變化

對於nologging模式,使用append hint 對資料沒有生成redo,僅對資料字典生成了redo.
APPEND hints on table "logging" not difference (generate redo). 
If  "alter table nologging"  before, and then insert (append)... it's work with nologging (not generate redo, just redo for data dictionary). 



三. 非歸檔模式下的示例


SQL> archive log list

資料庫日誌模式             非存檔模式

自動存檔             禁用

存檔終點            d:/archivelog

最早的聯機日誌序列     129

當前日誌序列           131

3.1  Create TABLE 

SQL> @?/new.sql

 OLD_VALUE

----------

    113788

SQL> create table T_NOLOG nologging as select * from all_objects;

表已建立。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -     113788) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

     87244

注:redo size=87244


SQL> @?/new.sql

 OLD_VALUE

----------

    201032

SQL> create table T_LOG logging as select * from all_objects;

表已建立。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -     201032) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

     81324

注: redo size=81324

 

總結: 在非歸檔模式下,create table nologging 和 logging 模式差別不大。
 When create table (noarchive mode) LOGGING table not different NOLOGGING table 

3.2  DML -- DELETE 

SQL> @?/new.sql

 OLD_VALUE

----------

    282356

SQL> DELETE FROM T_NOLOG;

已刪除71711行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -     282356) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  26591628

 

注: redo size=26591628


SQL> @?/new.sql

 OLD_VALUE

----------

  26873984

SQL> DELETE FROM T_LOG;

已刪除71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   26873984) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  26590272

注: redo size= 26590272

 

 

3.3  DML --  INSERT
SQL> @?/new.sql

 OLD_VALUE

----------

  53464256

SQL>  INSERT INTO T_NOLOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   53464256) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8170184
注:redo size = 8170184


SQL> @?/new.sql

 OLD_VALUE

----------

  61634440

SQL> INSERT INTO T_LOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   61634440) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8169840
注: redo size= 8169840

 

 

3.4 DML -- UPDATE


SQL> @?/new.sql

 OLD_VALUE

----------

  69804280

SQL> UPDATE T_NOLOG SET OBJECT_ID=1;

已更新71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   69804280) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  20164888

注: redo size = 20164888

SQL> @?/new.sql

 OLD_VALUE

----------

  89969168

SQL> UPDATE T_LOG SET OBJECT_ID=1;

已更新71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -   89969168) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

  21674776

 

注: redo size=21674776

總結: 對於 INSERT/UPDATE/DELETEDML 操作, nologging 和 logging 模式沒有什麼區別

  On DML INSERT/UPDATE/DELETE not different between NOLOGGING and LOGGING 

3.5  INSERT /*+ APPEND */ 


SQL> @?/new.sql

 OLD_VALUE

----------

 111643944

SQL> INSERT INTO T_NOLOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  111643944) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

   8325816

 

注: redo size=8325816


SQL> @?/new.sql

 

 OLD_VALUE

----------

 119969760

SQL> INSERT /*+ APPEND */ INTO T_NOLOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  119969760) OLD_VALUE from v$mystat, v$statname where

 OLD_VALUE

----------

     14896

 

注:redo size=14896 減小很多


SQL> @?/new.sql

 OLD_VALUE

----------

 119984656

SQL> INSERT INTO T_LOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  119984656) OLD_VALUE from v$mystat, v$statname where

 

 OLD_VALUE

----------

   8325832

注: redo size= 8325832


SQL> @?/new.sql

 OLD_VALUE

----------

 128310488

SQL> INSERT /*+ APPEND */ INTO T_LOG SELECT * FROM ALL_OBJECTS;

已建立71712行。

SQL> @?/diff

原值    1: select (value - &OLD_VALUE) OLD_VALUE from v$mystat, v$statname where

新值    1: select (value -  128310488) OLD_VALUE from v$mystat, v$statname where

 

 OLD_VALUE

----------

     14880

注:redo size=14880

 

總結: 對於非歸檔模式,對於nologging 和 logging模式,只有使用 append,才不會對資料生成redo。 

   對於歸檔模式,只有將表置於nologging 模式,並且使用append 才不會對資料生成redo. 

一點注意的地方:


                如果直接載入的表上有索引,Oracle不會像載入資料的方式那樣來處理索引的資料,但是它同樣需要維護一個索引,這個成本很高,同時會生成很多的redo

                所以當使用直接載入時,通常是針對一些資料量非常大的表。如果這些表存在索引,將會帶來很大的效能影響,這時可以考慮先將索引disable或者drop掉,等載入資料後,之後在重新建立索引。

 


On NoArchive Mode, Don't mind tables be nologging/logging...  just use /*+ APPEND */ ,that will not generate redo (just data dictionary) 

 

 


 

 


On Archive Mode, TABLEs must be nologging... and use  /*+ APPEND */, that will not generate redo (just data dictionary) 


 

NOLOGGING: Oracle will generate a minimal number of redo log entries in order to protect the data dictionary, and the operation will probably run faster. Logging can be disabled at the table level or the tablespace level.

If it is done at the tablespace level then we create indexes or tables in this tablespace; they will be in NOLOGGING mode.
A table or an index can be created with NOLOGGING mode or it can be altered using ALTER TABLE/INDEX NOLOGGING.

NOLOGGING is active in the following situations and while running one of the following commands but not after that.

- DIRECT LOAD (SQL*Loader)
- DIRECT LOAD INSERT (using APPEND hint)
- CREATE TABLE ... AS SELECT
- CREATE INDEX
- ALTER TABLE MOVE
- ALTER TABLE ... MOVE PARTITION
- ALTER TABLE ... SPLIT PARTITION
- ALTER TABLE ... ADD PARTITION (if HASH partition)
- ALTER TABLE ... MERGE PARTITION
- ALTER TABLE ... MODIFY PARTITION, ADD SUBPARTITON, COALESCE SUBPARTITON, REBUILD UNUSABLE INDEXES
- ALTER INDEX ... SPLIT PARTITION
- ALTER INDEX ... REBUILD
- ALTER INDEX ... REBUILD PARTITION

Logging is stopped only while one of the commands above is running.

So if a user runs this:  ALTER INDEX new_index NOLOGGING.

The actual rebuild of the index does not generate redo (all data dictionary changes associated with the rebuild will do) but after that any DML on the index will generate redo this includes direct load insert on the table which the index belongs to.

All the following statements will generate redo despite the fact the table is in NOLOGGING mode:
- INSERT INTO new_table_nolog_test ...,
- UPDATE new_table_nolog_test SET ...,
- DELETE FROM new_table_nolog_test ..

The following will not generate redo (except from dictionary changes and indexes):
- INSERT /*+APPEND+/ ...
- ALTER TABLE new_table_nolog_test MOVE ...
- ALTER TABLE new_table_nolog_test MOVE PARTITION ...

 

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

相關文章