1. append方式添加記錄對insert into ... values語句不起作用。
2. 以append方式批量插入的記錄,其存儲位置在hwm 之上,即使hwm之下存在空閑塊也不能使用。
3. 以append方式插入記錄后,要執行commit,才能對表進行查詢。否則會出現錯誤:
ORA-12838: 無法在并行模式下修改之后讀/修改對象
4. 在歸檔模式下,要把表設置為nologging,然后以append方式批量添加記錄,才會顯著減少redo數量。在非歸檔模式下,不必設置表的nologging屬性,即可減少redo數量。如果表上有索引,則append方式批量添加記錄,不會減少索引上產生的redo數量,索引上的redo數量可能比表的redo數量還要大。
用insert append可以實現直接路徑加載,速度比常規加載方式快。但有一點需要注意: insert append時在表上加“6”類型的鎖,會阻塞表上的所有DML語句。因此在有業務運行的情況下要慎重使用。若同時執行多個insert append對同一個表并行加載數據,并不一定會提高速度。因為每一時刻只能有一個進程在加載(排它鎖造成)。
SQL> create table test as select * from dba_objects where 1=2;
表已創建。
SQL> insert into test select * from dba_objects;
已創建11344行。
SQL> set lines 150
SQL> col object_type for a10
SQL> col object for a30
SQL> col username for a10
SQL> col osuser for a10
SQL> col program for a30
SQL> col sid for 99,999
SQL> col locked_mode for 99
SQL> col spid for 999,999
SQL> select o.object_type,o.owner||'.'||o.object_name object,s.sid,s.serial#,p.spid,s.username,s.osuser,s.program,l.lock
ed_mode
2 from v$locked_object l,dba_objects o,v$session s,v$process p
3 where l.object_id = o.object_id
4 and s.sid=l.session_id
5 and s.paddr=p.addr
6 and o.object_name = upper('&obj');
輸入 obj 的值: test
原值 6: and o.object_name = upper('&obj')
新值 6: and o.object_name = upper('test')
OBJECT_TYP OBJECT SID SERIAL# SPID USERNAME OSUSER PROGRAM
LOCKED_MODE
---------- ------------------------------ ------- ---------- ------------ ---------- ---------- ------------------------
------ -----------
TABLE SYS.TEST 147 19 784 SYS CNPEKALT02 sqlplus.exe
3
2\jyu
可以看到,insert 時在表上加的是“3”類型的鎖。
SQL> rollback;
回退已完成。
SQL> insert /*+ append */ into test select * from dba_objects;
已創建11344行。
SQL> set lines 150
SQL> col object_type for a10
SQL> col object for a30
SQL> col username for a10
SQL> col osuser for a10
SQL> col program for a30
SQL> col sid for 99,999
SQL> col locked_mode for 99
SQL> col spid for 999,999
SQL> select o.object_type,o.owner||'.'||o.object_name object,s.sid,s.serial#,p.spid,s.username,s.osuser,s.program,l.lock
ed_mode
2 from v$locked_object l,dba_objects o,v$session s,v$process p
3 where l.object_id = o.object_id
4 and s.sid=l.session_id
5 and s.paddr=p.addr
6 and o.object_name = upper('&obj');
輸入 obj 的值: test
原值 6: and o.object_name = upper('&obj')
新值 6: and o.object_name = upper('test')
OBJECT_TYP OBJECT SID SERIAL# SPID USERNAME OSUSER PROGRAM
LOCKED_MODE
---------- ------------------------------ ------- ---------- ------------ ---------- ---------- ------------------------
------ -----------
TABLE SYS.TEST 147 19 784 SYS CNPEKALT02 sqlplus.exe
6
2\jyu
而執行insert append時在表上加的是“6”類型的鎖。
insert append與一般的insert在表上加的鎖不一樣。insert append加的是exclusive的鎖。因此要注意在執行insert append盡快提交,否則會阻塞其它事務對同一張表的DML語句。
此外, ORA-12838:是由于在執行insert append之后沒有提交或回滾,接著又執行DML語句造成的。解決辦法是在insert append 之后加上commit或rollback。
請看下面的測試:
SQL> delete from test;
已刪除9831行。
SQL> insert /*+ append */ into test select * from temp_fsum_od;
已創建3277行。
SQL> insert into test select * from temp_fsum_od;
insert into test select * from temp_fsum_od
*
第 1 行出現錯誤:
ORA-12838: 無法在并行模式下修改之后讀/修改對象
SQL> update test set OD_CODE=upper(OD_CODE) ;
update test set OD_CODE=upper(OD_CODE)
*
第 1 行出現錯誤:
ORA-12838: 無法在并行模式下修改之后讀/修改對象
SQL> delete from test;
delete from test
*
第 1 行出現錯誤:
ORA-12838: 無法在并行模式下修改之后讀/修改對象
SQL>
SQL> insert /*+ append */ into test select * from temp_fsum_od;
insert /*+ append */ into test select * from temp_fsum_od
*
第 1 行出現錯誤:
ORA-12838: 無法在并行模式下修改之后讀/修改對象
注意,我先執行了一個delete語句,又執行了insert append. 這個delete語句并沒有造成后面的insert append報錯。
但在我執行了一個insert append之后,再執行任何DML語句都會報錯。
這說明,在執行了insert append 之后,必須commit或rollback,才能再執行其它DML語句。
但在insert append之前可以執行DML語句,而不會對insert append造成影響。
所以我們注意一點就可以了,即只要業務允許,在執行insert
insert append方法的使用
大家眾所周知,向
數據庫里插入數據有很多種方法,insert、sqlloader、for update等。每種方法都有其不同的特點。
但是每一種方法在其
服務器設置不同的情況下也是有不同的執行情況的。例如:insert。
insert 屬于DML語言(即數據操作語言,還包括select,delete,update)。網上介紹過一種insert append方法,語句格式為 insert /* +append+ */ into table_name select column_name1…… from table_name2 ; 這種方法據說可以占用很少的redo表空間,占用很少的redo表空間也就是省略了一些歸檔的時間,這樣是可以提高insert的執行效率的!但是經過測試我發現insert append并不是在任何時候都可以節省時間的。
第一種情況:database為archivelog狀態,這種情況下,就算你用insert append也是不一定提高插入效率的。但是如果你在建表的時候,將目標表建成nologging的,然后再使用insert append就會很快。
第二種情況:database為noarchivelog狀態,這種情況下,如果情況下采用insert方法向表中插入數據,占用的redo空間的大小與archivelog狀態下占用的大小是相當的,不論表是否為nologging。但是如果采用insert append方法的話,通過redo的占用值大家可以發現,不論表是否為nologging,所占用的redo的大小都是很小的。也就說明:在數據庫為noarchivelog的狀態下,采用insert append方法,如果表不是nologging,系統也會自動將表轉換為nologging(即在執行insert append之前,先執行一個alter table arch1 nologging;)。
以下為測試的具體過程:
-------- 數據庫為歸檔模式
create table arch (status varchar(2)) nologging; ----- create a nologging table
Table created
create table arch1 (status varchar(2)) ; ----- create a logging table
Table created
select a.name, b.value
from v$statname a, v$mystat b
where a.statistic# = b.statistic#
and a.name = 'redo size'
and b.value > 0; ----- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 1332780
insert into arch select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 1744516 ----- +411736
insert into arch1 select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 2156000 ------ +411484
insert /*+append*/ into arch select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 2169864 ----- +13864
insert /*+append*/ into arch1 select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 2555448 ----- +385584
spool off;
-------- 數據庫為非歸檔模式
create table arch (status varchar(2)) nologging; ----- create a nologging table
Table created
create table arch1 (status varchar(2)) ; ----- create a logging table
Table created
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 33208
insert into arch select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 444704 ----- +411496
insert into arch1 select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 856160 ----- +411456
insert /*+append*/ into arch select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 870024 ----- +13864
insert /*+append*/ into arch1 select 'ok' from dba_objects
29514 rows inserted
---- view redo engross space
NAME VALUE
---------------------------------------------------------------- ----------
redo size 884004----- +13980
spool off;