常見的insert方式有兩種:html
(1) insert into table_name values(....)數據庫
(2) insert into target_table select* from source_tablesession
上面這兩種常規的插入式,默認都是在串行方式下的插入,會將insert的數據寫入buffer_cache,插入前檢查表中是否有block中存有空閒空間能夠追加插入,並寫入redo log。app
(1) 能夠將insert數據跳過buffer_cahce,省掉了buffer block的格式化與DBWR操做,直接從PGA寫入磁盤less
(2) 不檢查表中現有的block是否有空閒空間,直接在表的高水位線(HWM)以上插入性能
(3) 若是在數據庫處於非歸檔模式下,或者是數據就處於歸檔模式,表級處於nologging狀態下,只有少許的空間信息redo寫入、不寫入數據undo(由於要回滾時能夠直接回退到高水線便可,而不須要針對insert生成delete的回滾記錄),因此在特定的狀況下,直接路徑(direct-path)的insert方式,在性能上遠遠快於常規的串行插入方式。ui
若是在數據庫處於歸檔模式,以及表處於logging模式下,直接路徑(direct-path)性能提高會大打折扣,由於,雖然direct-path能生效,可是仍然會記錄下完整的redo和undo。spa
也就是說,在歸檔模式下,還須要將表改爲nologging模式,纔不會寫數據的redo。日誌
Note: If the database or tablespace is in FORCE LOGGING mode, thenorm direct-path INSERT always logs, regardless of the logging setting. |
若是數據庫或表空間在forcelogging模式,則direct-path insert老是會寫日誌,不管logging如何設置。
如下爲ORACLE官方技術資料對APPENDhint的說明:
APPEND hint: Instructs the optimizer to use direct-path INSERT (data is appended to the end of the table, regardless of whether there is free space in blocks below the high watermark) |
當數據庫處於非歸檔模式下,無論表爲logging模式仍是nologging模式,使用/*+APPEND */ hint,既可使用direct-path,還將不記錄redo和undo
用法以下:
INSERT /*+ APPEND */ INTO new_object SELECT * FROM dba_objects; |
當數據庫處於歸模模式下,若表爲logging模式,即使使用/*+APPEND */ hint,雖然direct-path能夠起到做用,可是insert操做仍然會寫redo記錄,就算你在insert語句上加nologging也不會有效果,redo日誌與undo照寫不誤。
須要通修改表或修改索引,或修改表空間的no-logging模式來達到不寫redo與undo的效果
如下爲從metalink(文檔ID166727.1)中找到的技術資料:
The APPEND hint is required for using serial direct-load INSERT. Direct-load INSERT operations can be done without logging of redo information in case the database is in ARCHIVELOG mode. Redo information generation is suppressed by setting no-logging mode for the table, partition, or index into which data will be inserted by using an ALTER TABLE, ALTER INDEX, or ALTER TABLESPACE command. |
用法以下:
Alter table new_object nologging; INSERT /*+ APPEND */ INTO new_object SELECT * FROM dba_objects; |
DML並行模式下,direct-path插入方式是默認的,固然,在DML並行模式下若是想不使用direct-path插入,能夠經過加noappendhint實現。如下是DML並行模式下的direct-path插入:
並行DML的前提條件:
(1)ORACLE版本爲Oracle Enterprise Edition
(2)操做的會話開啓並行DML
(3)下面三項要求必須知足一項:
1)目標表上開啓並行屬性(DEGREE)
2)插入語句中指定並行提示(/*+ parallel n */)
3)有設置PARALLEL_DEGREE_POLICY參數的值爲AUTO
以數據庫爲非歸檔模式用法爲例(注意歸檔模式,還需將表改爲nologging模式): (1)alter session enable parallel dml; 語句還有選項有::ALTER SESSION { ENABLE | FORCE } PARALLEL DML; (2)alter table new_object_directpath parallel 8; (3)insert /*+PARALLEL(new_object_directpath, 8) */into new_object_directpathnologging select * from new_object_old; |
環境說明:
源表名 |
test_dba_objects |
源錶行數 |
1630104 |
源表segment大小 |
184MB |
操做步驟與性能對比結果以下:
傳統串行insert方式 |
APPEND hint的direct-path insert方式 |
DML並行的direct-path insert方式 |
(1)建表與修改設定 SQL>create table new_object_directpath as select * from test_dba_objects where 1=2
SQL>alter table new_object_directpath nologging SQL> SET TIMING ON Elapsed: 00:00:00.54
(2)insert耗時 SQL> insert into new_object_directpathnologgingselect * from test_dba_objects;
1630104 rows created.
Elapsed: 00:00:12.43 未產生數據redo與undo |
(1)建表與修改設定 SQL>create table new_object_directpath as select * from test_dba_objects where 1=2
SQL>alter table new_object_directpath nologging SQL> SET TIMING ON Elapsed: 00:00:00.54
(2)insert耗時 SQL> insert /*+APPEND */into new_object_directpath select * from test_dba_objects;
1630104 rows created.
Elapsed: 00:00:05.83 未產生數據redo與undo |
SQL>create table new_object_directpath as select * from test_dba_objects where 1=2
SQL>alter table new_object_directpath nologging SQL> SET TIMING ON Elapsed: 00:00:00.54
(2)修改表的並行模式 SQL> alter table new_object_directpath parallel 8;
(3) insert耗時 SQL> insert /*+parallel (new_object_directpath,8) */ into new_object_directpath select * from test_dba_objects;
1630104 rows created.
Elapsed: 00:00:05.61 未產生數據redo與undo |
http://www.2cto.com/database/201501/369138.html