흔히 대량 데이터를 insert 할 때 많은 DBA들이 append 힌트를 사용 하라고 한다.

근데 무작정 append 힌트 쓴다고 과연 빨라질까?


append 힌트는 데이터베이스가 noarchive mode 혹은 table을 nologging 으로 설정 시에만 사용 가능하다.


다음과 같은 상황에서 빠르게 insert 가 가능하다.

1. 대량의 redo를 발생시켜 archive mode에서 log switch를 방해. -> nologging 설정

2. append 힌트 사용시 direct load를 지원하여 버퍼캐쉬를 거치지 않아 rollback 정보 생성 안함.


대부분 위 사실을 다들 알고 있다.

근데 간과한 것이 하나 있으니 그것은 "INDEX" 다.

append 힌트 사용해서 열심히 insert 해도 인덱스가 있어서 다량의 redo와 index spilt으로 인한 성능 저하는 피할 수 없다.

인덱스를 다 날리고 작업을 하던가 아니면 인덱스를 비활성화 하고 진행하자.


1. alter index table1_idx unusable;

2. alter session set skip_unusable_indexes=true;

3. insert /*+ append */ into table1 select * from table2;

4. alter index big_table1_idx rebuild nologging;


여기서 또 중요한 사실이 하나 있으니 테이블 만들때 PK를 어떻게 만들었냐에 따라 에러를 만나게 될 수도 있다.


SQL> create table test1 (col1 number,

  2  col2 number);


Table created.

SQL> create unique index test1_pk on test1(col1);


Index created.

SQL> alter table test1 add constraints test1_pk primary key(col1);


Table altered.

SQL> alter index test1_pk unusable;


Index altered.

17:38:38 SQL> insert /*+ append */ into test1 select * from test2;


2 rows created.



SQL> create table test1

 2  (col1 number, col2 number, constraint test1_pk primary key(col1));


Table created.

SQL> alter index test1_pk unusable;


Index altered.

SQL> insert /*+ append */ into test1 select * from test2;

insert /*+ append */ into test1 select * from test2

                          *

ERROR at line 1:

ORA-26026: unique index SYS.TEST1_PK initially in unusable state



난 첫번째 방법으로 PK만드는 것을 선호한다.

좀 번거롭긴 하지만 tablespace도 지정할 수 있고, 삭제시 안전 장치도 된다.




'OraclE' 카테고리의 다른 글

dbms_scheduler 변경  (2) 2016.01.04
flashback  (0) 2015.04.27
object 변경시 dependency  (0) 2015.01.06
pid로 port 찾기 (lsof)  (0) 2014.09.17
logminor 로그마이너  (0) 2014.09.05

 

append 힌트의 효용성에 대한 논란이 잠시 있어 막간을 이용, 확인차 테스트해봤습니다..

 

아래 링크를 차례대로 읽어보세요...

 

i) NOLOGGING이 아닌 테이블에는 INSERT /*+ APPEND */ 효과가 없다?
   : "APPEND 힌트의 진실과 거짓" --> http://blog.naver.com/addibuddi/22476554

 

ii) http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:5280714813869

위 사이트에서 Kyte는 다음과 같이 정리함..

 

Table Mode    Insert Mode     ArchiveLog mode      result
-----------   -------------   -----------------    ----------
LOGGING       APPEND          ARCHIVE LOG          redo generated
NOLOGGING     APPEND          ARCHIVE LOG          no redo
LOGGING       no append       ""                   redo generated
NOLOGGING     no append       ""                   redo generated
LOGGING       APPEND          noarchive log mode   no redo
NOLOGGING     APPEND          noarchive log mode   no redo
LOGGING       no append       noarchive log mode   redo generated
NOLOGGING     no append       noarchive log mode   redo generated

 

이제 테스트를 시작합니다..

 

############################################
### 1. logging 테이블에 conventional INSERT
############################################

SQL> conn scott
Enter password:
Connected.

 

SQL> create table tab3 logging
as select * from all_objects
where 1=2;

Table created.


SQL> insert into tab3
select * from all_objects
;

36013 rows created.

 

SQL> commit;

Commit complete.

 

SQL> select * from v$sesstat
where sid = (select sid from v$mystat where rownum = 1)
and STATISTIC# = (
select STATISTIC# from v$statname
where name = 'redo entries') ;

 

       SID STATISTIC#      VALUE
---------- ---------- ----------
       282        133       3420   <====


SQL> explain plan for insert into tab3  
  2  select * from tab3 ;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1925526863

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | INSERT STATEMENT  |      | 37070 |  4633K|   129  (14)| 00:00:02 |    <====
|   1 |  TABLE ACCESS FULL| TAB3 | 37070 |  4633K|   129  (14)| 00:00:02 |
--------------------------------------------------------------------------

#######################################
### 2. logging 테이블에 Direct Insert
#######################################


SQL> conn scott
Enter password:
Connected.

SQL> create table tab1 logging
as select * from all_objects
where 1=2;

Table created.

 

SQL> insert /*+  append */ into tab1
select * from all_objects

36011 rows created.

 

SQL> commit;

Commit complete.

 

SQL> select * from v$sesstat
where sid = (select sid from v$mystat where rownum = 1)
and STATISTIC# = (
select STATISTIC# from v$statname
where name = 'redo entries') ; 

 

       SID STATISTIC#      VALUE
---------- ---------- ----------
       240        133        866   <====

 

SQL> explain plan for insert /*+  append */ into tab1
  2  select * from tab1;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1481117511

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | INSERT STATEMENT   |      | 32454 |  4056K|   126  (12)| 00:00:02 |
|   1 |  LOAD AS SELECT    | TAB1 |       |       |            |          |    <====
|   2 |   TABLE ACCESS FULL| TAB1 | 32454 |  4056K|   126  (12)| 00:00:02 |
---------------------------------------------------------------------------


#######################################
### 3. nologging 테이블에 Direct Insert
#######################################

SQL> conn scott
Enter password:
Connected.

SQL> create table tab2 nologging
as select * from all_objects
where 1=2;

Table created.

 

SQL> insert /*+  append */ into tab2
select * from all_objects
;

36012 rows created.

 

SQL> commit;

Commit complete.

 

SQL> select * from v$sesstat
where sid = (select sid from v$mystat where rownum = 1)
and STATISTIC# = (
select STATISTIC# from v$statname
where name = 'redo entries') ; 

 

       SID STATISTIC#      VALUE
---------- ---------- ----------
       118        133        363  <====


SQL> explain plan for insert /*+  append */ into tab2
  2  select * from tab2;

Explained.

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 4264119061

---------------------------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------
|   0 | INSERT STATEMENT   |      | 36080 |  4510K|   128  (14)| 00:00:02 |
|   1 |  LOAD AS SELECT    | TAB2 |       |       |            |          |    <====
|   2 |   TABLE ACCESS FULL| TAB2 | 36080 |  4510K|   128  (14)| 00:00:02 |
---------------------------------------------------------------------------

 

** 테스트 결과, logging 속성의 테이블이더라도 APPEND 힌트에 의한 REDO감소 효과는 큰것으로 나타남.

 

3420  > 866 > 363

 

이정도의 차이라면 Production환경에서는 recovery를 포기하고 테이블까지 nologging으로 해야 한다는 우를 범하지 않고서라도 충분히 append 힌트의 효용성을 누릴수 있을 것이다.

[출처] http://blog.naver.com/dbmedic?Redirect=Log&logNo=50040322413

'OraclE' 카테고리의 다른 글

Temporary Tablespace Group(10g)  (0) 2013.11.20
db link 사용시 lob타입 테이블 문제  (0) 2012.08.03
datapump  (0) 2012.06.20
DBMS_STATS  (0) 2012.06.13
DBMS_STATS 패키지  (0) 2012.06.13

+ Recent posts