來源於:http://blog.sina.com.cn/s/blog_61cd89f60102e7gi.html
當需要對一個非常大的表INSERT的時候,會消耗非常多的資源,因為update表的時候,oracle需要生成 redo log和undo log;此時最好的解決辦法是用insert, 並且將表設置為nologging;當把表設為nologging后,並且使用的insert時,速度是最快的,這個時候oracle只會生成最低限度的必須的redo log,而沒有一點undo信息。如果有可能將index也刪除,重建
1.alter table table_name nologging;
2. insert into table_name select * from xxxx;
對此有了更好的解決方法:
1、alter table nologging;
注釋:Nologging的設置跟數據庫的運行模式有關
a、查詢當前數據庫的歸檔狀態:
select name,log_mode from v$database;
默認為 NOARCHIVELOG 非歸檔
b、nologging在歸檔模式下有效,非歸檔模式nologging不起什么作用
c、為了提高插入的速度,我們可以對表關閉寫log功能。 SQL 如下:
插入/修改,完數據后,再修改表寫日志:
sql> alter table table_name LOGGING;
d、沒有寫log, 速度會塊很多,但是也增加了風險,如果出現問題就不能恢復。
2、drop掉索引約束之類的;
注釋:
3、
注釋:
a. 、append 屬於direct insert,歸檔模式下append+table nologging會大量減少日志,
非歸檔模式append會大量減少日志,append方式插入只會產生很少的undo
b、綜合一下吧:一是減少對空間的搜索;二是有可能減少redolog的產生。所以append方式會快很多,一般用於大數據量的處理
c、建議不要經常使用append,這樣表空間會一直在高水位上,除非你這個表只插不刪
d、oracle append有什么作用?
請教一下,oracle中append是做什么用的。
insert into table1 select * from table2
在使用了append選項以后,insert數據會直接加到表的最后面,而不會在表的空閑塊中插入數據。
使用append會增加數據插入的速度。
的作用是在表的高水位上分配空間,不再使用表的extent中的空余空間
append 屬於direct insert,歸檔模式下append+table nologging會大量減少日志,
非歸檔模式append會大量減少日志,append方式插入只會產生很少的undo
不去尋找 freelist 中的free block , 直接在table HWM 上面加入數據。
4、總結
測試證明:
1. 不管哪種模式下append要與nologging方式聯用才能達到很好的效果。
2. 非歸檔與歸檔方式,只用NOLOGGING是不起效果的。
3. 非歸檔下append已達到不錯的效果,但不及與nologging的聯用方式。
4. 歸檔下單append起不到效果。
NOLOGGING插完后最好做個備份。
另外,如果庫處在FORCELOGGING模式下,此時的nologging方式是無效的。
總結得出以下3點結論:
a、非歸檔模式下,只需append就能大量減少redo的產生;歸檔模式下,只有append+nologging才能大量減少redo。
b、insert /*+ append */ 時會對表加鎖(排它鎖),會阻塞表上的除了select以外所有DML語句;傳統的DML在TM enqueue上使用模式3(row exclusive),其允許其他DML在相同的模式上獲得TM enqueue。但是直接路徑加載在TM enqueue使用模式6(exclusive),這使其他DML在直接路徑加載期間將被阻塞。
c、insert /*+ append */ 直接路徑加載,速度比常規加載方式快。因為是從HWM的位置開始插入,也許會造成空間浪費。
數據庫版本:
SQL> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
網上說測試時不要使用auto trace來查看redo size,這個值是有偏差的.建議建立一個視圖:
SQL> create or replace view redo_size
2 as
3 select value
4 from v$mystat, v$statname
5 where v$mystat.statistic# = v$statname.statistic#
6 and v$statname.name = 'redo size';
視圖已創建。
一、非歸檔模式
SQL> archive log list
數據庫日志模式 非存檔模式
自動存檔 禁用
存檔終點 USE_DB_RECOVERY_FILE_DEST
最早的聯機日志序列 95
當前日志序列 97
1、nologging表
SQL> create table test1 nologging as select * from dba_objects where 1=0;
表已創建。
SQL> select * from redo_size;
VALUE
----------
25714940
SQL> insert into test1 select * from dba_objects;
已創建72753行。
SQL> select * from redo_size;
VALUE
----------
34216916
SQL> insert /*+ APPEND */ into test1 select * from dba_objects;
已創建72753行。
SQL> select * from redo_size;
VALUE
----------
34231736
SQL> select (34231736-34216916) redo_append , (34216916-25714940) redo_normal from dual;
REDO_APPEND REDO_NORMAL
----------- -----------
14820 8501976
2、logging表:
SQL> create table test2 as select * from dba_objects where 1=0;
表已創建。
SQL> select * from redo_size;
VALUE
----------
34273348
SQL> insert into test2 select * from dba_objects;
已創建72754行。
SQL> select * from redo_size;
VALUE
----------
42775336
SQL> insert /*+ APPEND */ into test2 select * from dba_objects;
已創建72754行。
SQL> select * from redo_size;
VALUE
----------
42790156
SQL> select (42790156-42775336) redo_append , (42775336-34273348) redo_normal from dual;
REDO_APPEND REDO_NORMAL
----------- -----------
14820 8501988
二、歸檔模式下:
SQL> shutdown immediate
數據庫已經關閉。
已經卸載數據庫。
ORACLE例程已經關閉。
SQL> startup mount
ORACLE例程已經啟動。
Total System Global Area 477073408 bytes
Fixed Size 1337324 bytes
Variable Size 293603348 bytes
Database Buffers 176160768 bytes
Redo Buffers 5971968 bytes
數據庫裝載完畢。
SQL> alter database archivelog;
數據庫已更改。
SQL> alter database open;
數據庫已更改。
SQL> archive log list
數據庫日志模式 存檔模式
自動存檔 啟用
存檔終點 USE_DB_RECOVERY_FILE_DEST
最早的聯機日志序列 95
下一個存檔日志序列 97
當前日志序列 97
1、nologging表
SQL> select * from redo_size;
VALUE
----------
17936
SQL> insert into test1 select * from dba_objects;
已創建72754行。
SQL> select * from redo_size;
VALUE
----------
8490972
SQL> insert /*+ APPEND */ into test1 select * from dba_objects;
已創建72754行。
SQL> select * from redo_size;
VALUE
----------
8506164
SQL> select (8506164-8490972) redo_append , (8490972-17936) redo_normal from dual;
REDO_APPEND REDO_NORMAL
----------- -----------
15192 8473036
2、logging表
SQL> select * from redo_size;
VALUE
----------
8506780
SQL> insert into test2 select * from dba_objects;
已創建72754行。
SQL> select * from redo_size;
VALUE
----------
16979516
SQL> insert /*+ APPEND */ into test2 select * from dba_objects;
已創建72754行。
SQL> select * from redo_size;
VALUE
----------
25518172
SQL> select (25518172-16979516) redo_append , (16979516-8506780) redo_normal from dual;
REDO_APPEND REDO_NORMAL
----------- -----------
8538656 8472736
在歸檔模式下,對於常規表的insert append產生和insert同樣的redo
此時的insert append實際上並不會有性能提高.
但是此時的append是生效了的。
三、insert /*+ append */會阻塞除select以外的DML語句,direct-path insert操作是單獨一個事務。
SQL> select count(*) from test2;
COUNT(*)
----------
291016
SQL> insert into test2 select * from dba_objects;
已創建72754行。
SQL> select count(*) from test2;
COUNT(*)
----------
363770
SQL> insert /*+ APPEND */ into test2 select * from dba_objects;
已創建72754行
同一個session下:
SQL> select count(*) from test2;
select count(*) from test2
*
第 1 行出現錯誤:
ORA-12838: 無法在並行模式下修改之后讀/修改對象
SQL> commit;
提交完成。
SQL> select count(*) from test2;
COUNT(*)
----------
436524
SQL> insert /*+ APPEND */ into test2 select * from dba_objects;
已創建72754行。
SQL> shutdown immediate
ORA-01097: 無法在事務處理過程中關閉 - 請首先提交或回退
SQL> select * from v$mystat where rownum<2;
SID STATISTIC# VALUE
---------- ---------- ----------
224 0 1
SQL> select KADDR,TYPE,LMODE from v$lock where sid=224;
KADDR TY LMODE
---------------- -- ----------
0000000071BAE180 TM 6
0000000070CB11B8 TX 6
另外開啟一個會話,就會發現只能select,其他DML全部阻塞。