언제 Conventional Data Load를 사용해야 하나?


만약에 데이터 적재 속도가 가장 중요하다면 direct path를 사용해야 한다. conventional path load보다 더 빠르기 때문이다. 그러나 direct path에 특정 제약조건이 있기 때문에 conventional path load를 사용해야 한다. 앞으로는 CPLconventional path load라고 하고 DPLdirect path load라고 하겠다.

 

구분

conventional path load

direct path load

속도

느림

빠름

가용성

로드 작업중 다른 유저가 테이블 수정 가능(가용성up)

로드 작업 중 다른 유저가 테이블 변경 불가(가용성down)

클러스터 테이블

클러스터 테이블에 load 가능

클러스터 테이블에 load 불가

인덱스

관련

인덱스가 걸린 큰 테이블에 소량의 행을 load할 경우(append) 유리

DPL에서는 인덱스를 로드 종료 후에 병합하는데 이때 기존 인덱스를 복사하고 병합한다. 만약 기존 인덱스가 크고 새로운 인덱스 키들이 작을 경우 DPL의 빠른 속도는 기존 인덱스를 복사하는 시간에 의해 상쇄 될 것이다.

제약조건

비교적 적은 수의 행을 큰 테이블에 로드하는데 참조 제약조건과 check 제약조건이 걸려있을 경우 CPL을 사용해야 한다.

DPL에서는 PRIMARY KEY, UNIQUE, NOT NULL만 검증한다.

INSERT

트리거

실행됨

실행되지 않음

 

Direct Path Load 장점


DPLCPL보다 빠른데 그 이유는 다음과 같다.

n  부분적인 블럭들은 사용되지 않는다, 그래서 읽을 블락을 찾을 필요가 없고 적은 쓰기만 수행된다.

n  INSERT가 사용되지 않는다.

n  로드 시작전에 테이블과 INDEXLOCK하고 로드가 끝난뒤에 LOCK을 푼다.

n  데이터파일에 대해 MULTIBLOCK ASYNCHRONOUS I/O를 사용한다.

n  DPL 도중에 프로세스들은 오라클의 버퍼캐시를 사용하는 대신 각자의 쓰기 I/O를 수행한다. 이는 다른 오라클 유저와의 경합을 줄인다.

n  적재되는 테이블이 비어있으면 사전정렬 옵션이 인덱스 생성의 정렬과 병합 단계를 제거한다. 인덱스는 데이터가 도착하는대로 채워진다.

n  인스턴스 장애에 대한 보호가 요구되지 않기에 리두 파일의 IO가 줄어든다. 다음 상황에서 로그파일에 쓰기 과정이 필요없다.

n  DBNOARCHIVELOG 모드일 때

n  SQL*LoaderUNRECOVERABLE 문이 활성화되었을 때

n  SQLNOLOGGING이 적용되었을 경우

 

Direct Path Load의 제약사항


n  클러스터테이블에는 적재될 수 없다.

n  Virtual Private Database(VPD) 정책이 Insert에 활성화된 테이블에는 적재될 수 없다

n  적재되어야할 세그먼트에 트랜잭션이 추가될 수 없다.

n  부모 테이블과 자식 테이블을 함께 적재할 수 없다.

n  BFILE 컬럼을 로딩할 수 없다.

n  적재 중에 CREATE SEQUENCE를 사용할 수 없다. DPLinsert 문을 생성하지 않고 로드를 진행하기 때문에 next value를 불러올 수 없다.

 

Direct Path LoadSingle Partition 제약사항


n  글로벌 인덱스를 가지고 있는 파티션에는 적재할 수 없다,

n  트리거 활성화 불가하다

n  참조와 체크조건이 걸려있는 테이블의 파티션에 대한 적재를 할 수 없다.

 

언제 Direct Path Load를 사용해야 하나?

만약 위의 제약사항에 해당되지 않는다면 아래 상황에서 direct path를 사용하는 것이 좋다.

n  많은 데이터를 빠르게 적재하고 싶을 때,

n  데이터 로드시 성능을 최대로 써서 병렬로 진행하고 싶을 때

 

Direct Path Load 주의사항


n  Check와 참조무결성 제약조건은 DPL시에 자동으로 적재시작 전에 비활성화되며, 적재 완료 후에 반드시 수동으로 활성화시켜야 한다. 이를 자동으로 활성화하게 하려면 REENABLE DISABLED_CONSTRAINTS 절을 컨트롤 파일에 기록해줘야 한다.

n  Check 제약조건은 EVALUDATE CHECK_CONSTRAINTS를 컨트롤 파일에 기록하면 비활성화하지 않게 할 수 있다.

n  INSERT 트리거는 적재 시작전에 비활성화된다. 그리고 적재 완료 후에 자동으로 활성화된다. 즉 그 동안 INSERT된 행들에 대한 트리거는 동작하지 않는다.

n  테이블의 DEFAULTDPL에선 사용할 수 없다. 이를 DEFAULT 적용하려면 DEAFULTIF 를 사용해야 한다. DEFAULTIF를 쓰지 않으면 NULL이 입력된다.

 

 

이 외에도 많은 내용이 더 있다.

http://docs.oracle.com/cd/E11882_01/server.112/e22490/ldr_modes.htm#SUTIL009

'Knowledge > Oracle' 카테고리의 다른 글

impdp, imp 주의사항  (0) 2016.03.20
Oracle Create Table 내부 절차  (0) 2015.10.21
undo 관련 좋은 링크  (0) 2015.09.15
null 관련 주의사항  (0) 2015.07.10
logon trail trigger on oracle  (0) 2015.01.22
Posted by neo-orcl
,

개요


http://blog.oracle48.nl/oracle-database-undo-space-explained/

 

만약 active undo extents만 존재하여 더이상 해당 트랜잭션에 대한 undo 공간을 확보할 수 없을 경우 ORA-30036 unable to extend segment in Undo tablespace 에러를 받게 되고 자동으로 트랜잭션은 rollback되게 된다.

이 현상이 얼마나 일어났는지 확인은 아래 sql을 통해 가능하다.

 

SQL> select sum(NOSPACEERRCNT) from v$undostat;

 

만약 active상태의 extents이 필요한데 expired extents이 없다면 unexpired(undo_retention 기간이 아직 지나지 않은 상태) extents를 빼앗게(steal) 되는데 해당 count를 확인하는 법은 아래와 같다.

 

SQL> select sum(unxpstealcnt) from v$undostat;

 

※ steal 못하게 하려면 undo 테이블스페이스에 대해 retention guarantee 옵션을 주면 된다.

SQL> alter tablespace undotbs1 retention guarantee;

단.. 이러면 이제 unexpired extent를 뺏지 않기 때문에 조금 긴 dml의 경우 실패할 경우가 자주 생길 것이다. 이는 즉 ORA-30036과 ORA-01555 중 어느것을 선택하느냐이다.

 

만약 이렇게 steal된 unexpired extents에 대해 read consisteny read 수행하면 ORA-01555 snapshot too old 발생하고 이 역시 v$undostat에서 확인 가능하다.

 

SQL> select sum(ssolderrcnt) from v$undostat;

 

※ undo extent 크기와 퍼센트를 확인하는 쿼리. 단 free는 포함되지 않음

 

select status,
  round(sum_bytes / (1024*1024), 0) as MB,
  round((sum_bytes / undo_size) * 100, 0) as PERC
from
(
  select status, sum(bytes) sum_bytes
  from dba_undo_extents
  group by status
),
(
  select sum(a.bytes) undo_size
  from dba_tablespaces c
    join v$tablespace b on b.name = c.tablespace_name
    join v$datafile a on a.ts# = b.ts#
  where c.contents = 'UNDO'
    and c.status = 'ONLINE'
);

 

■ undo size tune


undo tablespace size가 고정되어있다면 오라클이 retention time을 undo 생성량에 따라 최적값을 찾게 된다. 하지만 undo tablespace 크기가 크다면 이를 크게 잡게 될 것이다.

이는 아래 쿼리로 확인 가능하다.

 

SQL> select tuned_undoretention from v$undostat;

 

이 경우 undo_retention parameter는 "최소 undo retention"이 된다.

undo retention autotune은 '_undo_autotune' hidden parameter를 설정해 끌 수도 있다.

 

■ undo_retention 값을 가장 긴 쿼리에 맞춰 설정하기


ORA-01555 에러를 피하기 위해 가장 긴 쿼리에 맞춰 undo retention을 설정하는 방법을 생각할 수 있다.

 

최근 7일간 가장 긴 쿼리의 길이(초)를 확인하는 방법

SQL> select max(maxquerylen) from v$undostat

'Knowledge > Oracle' 카테고리의 다른 글

Oracle Create Table 내부 절차  (0) 2015.10.21
SQL Loader Direct Load  (0) 2015.10.05
null 관련 주의사항  (0) 2015.07.10
logon trail trigger on oracle  (0) 2015.01.22
oracle 접속 ip 차단하기  (0) 2015.01.22
Posted by neo-orcl
,

1. 기본문. 예외처리가 없음(20)
declare
        v_department_id em.department_id%type := &deptno;
        dummy number;
begin
        select 1
        into dummy
        from em
        where department_id = v_department_id;
        dbms_output.put_line('ok');
end;
/

 

2. 사전정의된 예외처리방법(20)
declare
        v_department_id em.department_id%type := &deptno;
        dummy number;
begin
        select 1
        into dummy
        from em
        where department_id = v_department_id;
        dbms_output.put_line('ok');
exception
        when too_many_rows then
          dbms_output.put_line('too many rows return');
        when others then
          dbms_output.put_line(sqlerrm);
end;
/

 

3. 사전정의안된 오류 예외처리 방법(20). too_many_rows 가 없다고 가정
declare
        v_department_id em.department_id%type := &deptno; --deptno를 받음
        dummy number;   --의미없지만 select가 돌아가게 하기 위해
       
        toomany exception;                     --1. exception 명 선언
        pragma exception_init(toomany, -1422);  --2.
begin
        select 1
        into dummy  --의미없지만 select가 돌아가게 하기 위해
        from em
        where department_id = v_department_id;
        dbms_output.put_line('ok');
exception
        when toomany then
          dbms_output.put_line('too many rows return');
        when others then
          dbms_output.put_line(sqlerrm);

end;
/

 

4. 유저 정의 예외처리(300) 에러메시지 발생, 중지
declare
        v_department_id em.department_id%type := &deptno;
        dummy number;
begin
        if v_department_id >= 300 then
          raise_application_error(-20000, '300이상의 값을 입력하지 마시옵소서');
        else
          select 1
          into dummy
          from em
          where department_id = v_department_id;
            dbms_output.put_line('ok');
        end if;
exception
        when others then
          dbms_output.put_line(sqlerrm);

end;
/

 

5. 유저 정의 예외처리(300) 실행 후 에러 메시지 정상 핸들링
declare
        v_department_id em.department_id%type := &deptno;
        dummy number;
        over_dept_err exception;
        pragma exception_init(over_dept_err, -20000);

begin
        if v_department_id >= 300 then
          raise_application_error(-20000, '300이상의 값을 입력하지 마시옵소서');
        else
          select 1
          into dummy
          from em
          where department_id = v_department_id;
            dbms_output.put_line('ok');
        end if;
exception
        when over_dept_err then
          dbms_output.put_line(sqlerrm);
        when others then
          dbms_output.put_line(sqlerrm);
end;
/

 

이거 말고 더 예제는 있습니다.

 

 

'Knowledge > PLSQL' 카테고리의 다른 글

After each row Trigger sample  (0) 2015.10.20
Posted by neo-orcl
,