분류

2019년 6월 21일 금요일

대용량 데이터 처리 4. DBMS_JOB

1. DBMS_JOB 언제 씁니까? 

통계 위주의 시스템을 구축하다보면 자주 발생하는 것이 대량의 데이터에 대한 일괄처리입니다. 배치잡은 주로 PROCEDURE로 이루어져 있고, 이런것들을 실행 시키는데는 많은 시간이 들어갑니다. 하지만 WEB에서 수행하는 환경에서 프로시저의 종료시간을 기다리는 것은 쉽지 않습니다.

사용자들이 실행 후 브라우저를 닫으면 결과값을 받지 못하므로 모니터링 프로그램에 오류로 남기도 하고, 모니터링 프로그램의 종류에 따라서는 30분이 지난 프로세스를 일괄적으로 삭제해버리는 기능이 있는 것들도 있기에 웹 환경에서 장시간이 걸리는 데이터 프로시저를 수행시킬 때 사용하게 됩니다.

또한 주기적으로 수행되는 작업을 관리할때에도 사용합니다.

예를들자면
BEGIN 프로시저(변수) END; 와 같은 구문을 웹에서 실행시킬 경우 해당 THREAD가 아닌 일반적인 WEB CONTROLLER에서는 프로시저의 수행 종료를 대기합니다. 하지만 JOB으로 실행시킬 경우 구문 수행후 대기 없이 종료되며 프로시저나 패키지는 DBMS에 의해 수행됩니다.

2. 오라클 DBMS_JOB 명령어 

DBMS_JOB을 실행할 수 없다면 DB관리자에게 DBMS_JOB 패키지에 대한 사용 권한을 요청해야 합니다.

가. JOB 목록 확인

SELECT * FROM USER_JOBS

나. 작업등록

작업 등록 명령어의 각 속성들은 아래와 같습니다. 
DBMS_JOB.SUBMIT(
               JOB ID    작업번호 - 숫자 타입의 빈 변수를 할당해주면 자동으로 적용 자동
              , WHAT   파라미터를 포함한 작업대상 저장 프로시저, 임의 프로시저를 문자열 형태로 입력할 수 있습니다. VARCHAR 4000
              , NEXT_DATE 다음 수행일시 : 기본값은 SYSDATE로 작업의 최초 수행시간 DATE
              , INVERVAL  반복 작업 수행시 다음 작업이 수행될 시간을 계산하는 함수  VARCAHR 200
              , NO_PARSE 구문검사와 작업대상 객체의 상태검사를 수행하지 않게 하는 옵션으로 기본값은 false이며 true로 변경할 경우 예약 하는 패키지나 작업대상 테이블이 없더라도 예약이 가능합니다.  boolean
              , INSTANCE 작업 수행에 사용할 인스턴스를 입력합니다. (다중 인스턴스인 경우 수행 인스턴스를 특정하기 위한 옵션인것 같습니다.) 인스턴스 번호 
              , FORCE   기본값은 false이며, true로 할 경우 인스턴스의 상태와 관계 없이 모든 인스턴스를 번호를 입력할 수 있습니다. False일경우 실행중인 인스턴스만 입력할 수 있습니다. boolean
  );

사용예
ㄱ) 1회성 작업의 즉시 실행 예약
DECLARE
    JOB_NO NUMBER;
    JOB_NAME VARCHAR2(4000);
BEGIN
   JOB_NAME := 'TESTPROC('''||#변수#||''');';
   DBMS_JOB.SUBMIT(JOB_NO, JOB_NAME);
  /*대부분의 속성이 기본값을 갖고 있기에 생략할 수 있습니다. 이렇게 잡을 수행시킬 경우 1회 수행 후 목록에서 사라집니다. */
END;

ㄴ) 반복예약
DECLARE
    JOB_NO NUMBER;
    JOB_NAME VARCHAR2(4000);
BEGIN
   JOB_NAME := 'TESTPROC('''||#변수#||''');';
   DBMS_JOB.SUBMIT(
                             JOB_NO
                           , JOB_NAME
                           , SYSDATE
                           , 'SYSDATE + 1'
                           );
END;

반복 예약의 경우 interval 이 중요합니다. INTERVAL 세팅에 대한 자세한 정보는 다른 블로그를 참조하시면 될 것 같습니다.  원하는 시간에만 DB 작업 실행하기

다. 작업변경 

작업 변경의 경우 no_parse 옵션이 없는 것을 제외하면 나머지가 작업 예약과 동일합니다. 
MS_JOB.CHANGE(    

JOB ID USER_JOBS테이블에서 확인할 수 있는 작업번호숫자
   , WHAT 파라미터를 포함한 작업대상 저장 프로시저, 임의 프로시저를 VARCHAR 4000
문자열 형태로 입력할 수 있습니다.
 , NEXT_DATE 다음 수행일시 : 기본값은 SYSDATE, 작업 시작시간                 DATE
 , INVERVAL  반복 작업 수행시 다음 작업이 수행될 시간을 계산하는 함수  VARCAHR 200
 , INSTANCE 작업 수행에 사용할 인스턴스를 입력합니다. (다중 인스턴스인 인스턴스 번호 
 경우 수행 인스턴스를 특정하기 위한 옵션인것 같습니다.)
  , FORCE 기본값은 false이며, true로 할 경우 인스턴스의 상태와 관계 없이 모든 인스턴스를 번호를 입력할 수 있습니다. False일경우 실행중인 인스턴스만 입력할 수 있습니다. boolean
    );      

라. 기타명령 

작업 중지
DBMS_JOB.BROKEN(  
 JOB IDUSER_JOBS테이블에서 확인할 수 있는 작업번호숫자
 BROKENtreu일경우 작업의 수행을 정지시킴 (수행되고 있는 작업이 있을경우 완료된 후 ) false일 경우 수행 정지를 해제 BOOLEAN
 ,NEXT_DATE작업 수행 시작일시 DATE
   );   

작업삭제 
DBMS_JOB.REMOVE(  
 JOB IDUSER_JOBS테이블에서 확인할 수 있는 작업번호숫자
   );   

보통 이정도만 알고있으면 대게 사용하는데 지장이 없습니다. 그 외에도 INSTANCE 변경,INTERVAL 변경, NEXT_DATE 변경 등 다양한 옵션이 있습니다. 그렇지만 CHANGE 하나만 알면 개별적인 것들은 중요하지 않기에 기술하지 않겠습니다.

10G 이후에는 SCHEDULER 를 통해서도 비슷한 작업을 수행할 수 있습니다. 더 발전된 형태이고 쓰기도 편하긴 합니다. 

이상입니다. 수정이나 의견이 있으신 분은 댓글 달아주시면 고맙겠습니다.


연관된 문서가 있습니다.
대용량 데이터 처리 1. java 다중쓰레드 활용
대용량 데이터 처리 2. 오라클 병렬처리 parallel
대용량 데이터 처리 3. 테이블 파티셔닝
대용량 데이터 처리 4. DBMS_JOB

2019년 6월 17일 월요일

대용량 데이터 처리 3. 테이블 파티셔닝

1.테이블 파티셔닝은 언제씁니까? 

대용량 데이터 처리를 하다 보면 자주 대량의 데이터에 대한 DELETE/INSERT 가 발생합니다. 이럴경우 데이터의 양에 따라서 삭제지연이 발생하기도 하고, 대량의 데이터에 대한 집계처리를 할 때도 분할영역이 존재하지 않으면 인덱스를 사용하더라도 속도가 더딘 일이 자주 있습니다. 이럴 경우 테이블 분할이나 파티셔닝을 사용하고 있습니다.

일단 테이블 분할에 대한 기본적인 개념을 알아야 합니다. 기본 개념은 다음과 같습니다.
a. 테이블의 특정 컬럼만 자주 조회/변경 되는 경우 수직분할
b. 특정 값에 해당하는 데이터에 대한 조회/변경이 잦은 경우 수평분할
c. 범위(기간)에 따라 변동되는 데이터에 대한 조회/변경이 잦은 경우 범위분할

여기서 수직 분할은 컬럼 단위, 수평 분할은 데이터의 특정 값을 기준으로 파티션을, 범위 분할은 특정 열값의 범위로 파티셔닝을 합니다.

또한 개념에서 주의하셔야 할 점은 수직 분할의 경우 테이블의 설계를 물리적으로 분할한다는 개념이지 테이블의 PARTITION 으로 구현되는 것이 아닙닌다. 따라서 자세한 내용이 나오진 않습니다. 파티셔닝은 수평분할과 범위분할에 사용되나봅니다.

2. 파티셔닝 사용시 장점은 무엇입니까? 

오라클 IN 메모리 오버뷰

파티션을 분할 한경우 파티션 키를 통해 특정 파티션의 데이터만 엑세스 하는 것이 가능합니다. 불필요한 데이터를 로드할 필요가 없어 엑세스 성능이 향상됩니다.

또한 커다란 테이블을 물리적인 위치를 분산시켜 대량의 데이터 입출력에 따르는 IO 부하를 분산시키는 효과도 있습니다.

파티션 단위로 데이터를 관리할 경우 입/출력 속도에 매우 중대한 영향이 생깁니다. 개인적으로는 1000만건 이상의 데이터에 대한 일괄 삭제/입력이 잦을 삭제시간 15분~30분을 줄이기 위해 파티션에 대한 drop이나 truncate를 사용합니다.

데이터에 대한 백업,변경 등의 관리를 파티션 단위로 할 수 있습니다.


3. 파티셔닝 개념 

일단 그림을 첨부하겠습니다.

1. 오라클의 데이터 저장소는 물리적으로 하나 이상의 데이터 파일로 이루어집니다.

2. 테이블 스페이스는 논리적으로 데이터를 저장하는 장소로 하나 이상의 데이터 파일을 포함하고 있습니다.

3.테이블이나 인덱스는 기본적으로 하나의 테이블 스페이스에 저장됩니다.

4. 파티션 테이블은 하나 이상의 테이블 스페이스에 파티션을 저장할 수 있습니다.

5. 테이블 데이터의 파티셔닝 기준은 특정키의 값이나 범위일 수 있습니다.

따라서 테이블 파티셔닝을 할 경우 특정 범위의 데이터에 대한 입출력이 잦은 경우 범위파티셔닝(범위), 특정 항목값에 의해 데이터 그룹이 분리되는경우(리스트) 파티셔닝을 하여 서로 다른 테이블 스페이스에 배치하여 입출력을 분산시킬 수 있으며, 관리 편의성을 확보할 수 있습니다. 같은 테이블 스페이스 내에서 여러 파티션을 관리하는 경우도 있습니다. (이 경우에도 어느정도의 성능 향상을 기대할 수 있습니다.)

4. 파티셔닝 명령어 

전체적은 파티션에 대한 내용을 모두 기술하기엔 무리가 있으므로, 제가 자주 사용하는 파티션에 대한 내용 몇가지만 간략하게 기술하겠습니다.

가. 파티션 사용 

1) 리스트 파티션
ㄱ) 생성
리스트파티션은 컬럼의 특정 값에 따라 데이터를 분할할 수 있을 경우 사용합니다.

CREATE TABLE 테이블명
(
 컬럼명1 VARCHAR2(20)
, 컬럼명2 VARCHAR2(20)
)
PARTITION BY LIST (컬럼명1)
(
 PARTITION 파티션명1 VALUE('값1') TABLESPACE 테이블스페이스1
, PARTITION 파티션명2 VALUE('값2') TABLESPACE 테이블스페이스1
, PARTITION 파티션명3 VALUE('값3') TABLESPACE 테이블스페이스2
)

ㄴ) 추가
ALTER TABLE 테이블명 ADD PARTITION 파티션명4 VALUES('값4') TABLESPACE 테이블스페이스2;

ㄷ) 드롭
ALTER TABLE 테이블명 DROP PARTITION 파티션명4;

ㄹ) 비움
ALTER TABLE 테이블명 TRUNCATE PARTITION 파티션명3;

ㅁ) 조회
SELECT * FROM 테이블명 PARTITION (파티션명1);

주의 : PARTITION 테이블에 테이블 전체에 대한 인덱스가 걸려있을 경우 DROP이나 TRUNCATE 후 INDEX REBUILD 를 해야 합니다.

ALTER TABLE 인덱스명 REBUILD;

2) 범위 파티션
ㄱ) 생성
CREATE TABLE 테이블명(
  컬럼명1 VARCHAR2(20)
 , 컬럼명2 VARCHAR2(20)
)
PARTITION BY RANGE (컬럼명1)
(
 PARTITION 파티션1 VALUES LESS THAN ('01') TABLESPACE 스페이스1
PARTITION 파티션2 VALUES LESS THAN ('05') TABLESPACE 스페이스1
PARTITION 파티션3 VALUES LESS THAN ('10') TABLESPACE 스페이스2
)

ㄴ) 추가
ALTER TABLE 테이블명 VALUES LESS THAN ('20') TABLESPACE 스페이스3

특이사항 : RANGE 파티션은 LIST와 달리 1개 이상의 컬럼을 기준으로 작성할 수 있습니다.
예) : CREATE TABLE 테이블명(
  컬럼명1 VARCHAR2(20)
 , 컬럼명2 VARCHAR2(20)
)
PARTITION BY RANGE (컬럼명1, 컬럼명2 )
(
 PARTITION 파티션1 VALUES LESS THAN ('01', '2009') TABLESPACE 스페이스1
,  PARTITION 파티션2 VALUES LESS THAN ('05', '2014') TABLESPACE 스페이스1
,  PARTITION 파티션3 VALUES LESS THAN ('10', '2019') TABLESPACE 스페이스2
)

DROP이나 TRUNCATE의 경우 LIST PARTITION과 같습니다.

이상입니다. 수정이나 의견이 있으신 분은 댓글 달아주시면 고맙겠습니다.


연관된 문서가 있습니다.
대용량 데이터 처리 1. java 다중쓰레드 활용
대용량 데이터 처리 2. 오라클 병렬처리 parallel
대용량 데이터 처리 3. 테이블 파티셔닝
대용량 데이터 처리 4. DBMS_JOB