insert中啓用錯誤日誌的問題及分析

在平時的工作中,有時候需要insert一批數據,這些數據可能是臨時表,外部表,普通表,子查詢等形式,類似下面的格式

insert into xxxx (select xxxxx from xxx where xxxxx);

如果其中有冗餘數據的時候,整個Insert會自動rollback,一條數據也插不進去,錯誤類似下面的形式。

insert /*+ append */into mo1_memo select *from MO1_MEMO_EXT_92;

*

ERROR at line 1:

ORA-00001: unique constraint (MIG_TEST.MO1_MEMO_PK) violated

可能我們想保證正常數據能夠插入,對於違反約束等的數據稍後處理,這個是用錯誤日誌就是一個很好的選擇。

首先就是創建錯誤日誌,可以使用提供的包來創建,也可以手動創建。

這裏我需要用到表含有lob字段,創建錯誤日誌的時候有下面的錯誤。

EXEC DBMS_ERRLOG.create_error_log(dml_table_name => 'MO1_MEMO')

BEGIN DBMS_ERRLOG.create_error_log(dml_table_name => 'MO1_MEMO'); END;

ERROR at line 1:

ORA-20069: Unsupported column type(s) found: MEMO_SYSTEM_TEXT_C

ORA-06512: at "SYS.DBMS_ERRLOG", line 235

ORA-06512: at line 1

不過想想也是合理的。不過問題還是要解決的。

可以看看創建錯誤日誌的包,Oracle已經考慮到了,我們可以忽略這種不支持的類型,當然還可以指定錯誤日誌的名字。 

SQL> desc dbms_errlog

PROCEDURE CREATE_ERROR_LOG

Argument Name Type In/Out Default?

------------------------------ ----------------------- ------ --------

DML_TABLE_NAME VARCHAR2 IN

ERR_LOG_TABLE_NAME VARCHAR2 IN DEFAULT

ERR_LOG_TABLE_OWNER VARCHAR2 IN DEFAULT

ERR_LOG_TABLE_SPACE VARCHAR2 IN DEFAULT

SKIP_UNSUPPORTED BOOLEAN IN DEFAULT

我們創建錯誤日誌

SQL> EXEC DBMS_ERRLOG.create_error_log(dml_table_name => 'MO1_MEMO',SKIP_UNSUPPORTED=>true,ERR_LOG_TABLE_NAME=>'MO1_MEMO_ERROR'); 

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.03

嘗試插入有冗餘的數據,

SQL> insert /*+ append */into mo1_memo select *from MO1_MEMO_EXT_92 LOG ERRORS INTO MO1_MEMO_ERROR('test_unique') REJECT LIMIT UNLIMITED

2 /

insert /*+ append */into mo1_memo select *from MO1_MEMO_EXT_92 LOG ERRORS INTO MO1_MEMO_ERROR('test_unique') REJECT LIMIT UNLIMITED

*

ERROR at line 1:

ORA-00001: unique constraint (MIG_TEST.MO1_MEMO_PK) violated

Elapsed: 00:00:17.32

直接拋了錯誤,看來錯誤日誌沒有正確啓用。

查看錯誤日誌,裏面也是空的。

SQL> SELECT *FROM MO1_MEMO_ERROR; --no rows

反覆嘗試,最後發現是Hint的原因,去掉Hint 就沒有問題了。

SQL> insert into mo1_memo select *from MO1_MEMO_EXT_92 LOG ERRORS INTO MO1_MEMO_ERROR('test_unique') REJECT LIMIT UNLIMITED;

99 rows created.

Elapsed: 00:04:04.83

1* select count(*)from mo1_memo_error

SQL> /

COUNT(*)

----------

907544     

錯誤日誌裏面有詳細的數據信息。但是如果足夠細心查看執行時間的話,就會發現如果不使用append,性能就會差很多。

下面是一個簡單的測試,

如果不使用append的時候,插入80萬左右的數據在1分鐘左右,如果使用了append就只需要大概13秒左右。

還有上面的測試結果,如果80萬記錄中99%左右的數據有冗餘,插入錯誤日誌就需要大概4分鐘的樣子

SQL> insert into mo1_memo select * from mo1_memo_ext_99 LOG ERRORS INTO MO1_MEMO_ERROR REJECT LIMIT UNLIMITED;

877245 rows created.

Elapsed: 00:01:12.91      

SQL> insert into mo1_memo select * from mo1_memo_ext_98;

753637 rows created.

Elapsed: 00:01:04.75     

SQL> rollback;

Rollback complete.

Elapsed: 00:00:56.35

SQL> insert /*+append*/ into mo1_memo select *from mo1_memo_ext_98;

753637 rows created.

Elapsed: 00:00:13.20

所以啓用錯誤日誌可以根據大家的需求來選擇,有利有弊。

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