DB(Database)/ORACLE

Program Parallel 방식의 진화 DBMS_PARALLEL_EXECUTE: 3. NUMBER Column 분할 방식의 병렬 처리 사례

ProDA 2021. 6. 30.

이 글은 새로운 블로그로 옮겼습니다. 5초후 자동으로 이동합니다.

▶ 새로운 블로그 주소: https://prodskill.com/

▶ 새로운 글 주소: https://prodskill.com/oracle-dbms-parallel-execute-3-chunk-by-number-column/

목차


    이전 글에서 이어지는 내용이다.

    2021.06.29 - [DB(Database)] - Program Parallel 방식의 진화 DBMS_PARALLEL_EXECUTE: 2.5. 작업 단위 분할 상세 확인

     

    Program Parallel 방식의 진화 DBMS_PARALLEL_EXECUTE: 2.5. 작업 단위 분할 상세 확인

    목차 이전 글에서 이어지는 내용이다. 2021.06.29 - [DB(Database)] - Program Parallel 방식의 진화 DBMS_PARALLEL_EXECUTE (2) Program Parallel 방식의 진화 DBMS_PARALLEL_EXECUTE (2) 목차 이전 글에서 이..

    prodtool.tistory.com


     

    3. NUMBER Column 분할 방식의 병렬 처리 사례

    NUMBER Column에 의한 분할방식의 사례를 살펴보자.

    ROWID 방식과 거의 유사한데, 다음 항목만 조금 다르다.

    • 작업 단위 분할시에 CREATE_CHUNKS_BY_NUMBER_COL procedure를 사용
    • 작업 실행시 SQL Statement의 WHERE절에 NUMBER column을 사용

     

    3.1. 작업 생성

    작업을 생성하는 방법은 차이가 없다.

    -- 1단계: 작업생성
    BEGIN
      DBMS_PARALLEL_EXECUTE.CREATE_TASK(TASK_NAME => 'DPE_TEST(BY NUMBER)');
    END;
    /
    
    -- 작업 생성 확인
    SELECT *
      FROM USER_PARALLEL_EXECUTE_TASKS
     WHERE TASK_NAME = 'DPE_TEST(BY NUMBER)';

     

    3.2. 작업 단위 분할

    CREATE_CHUNKS_BY_NUMBER_COL(<TASK_NAME>, <TABLE_OWNER>, <TABLE_NAME>, <TABLE_COLUMN>, <CHUNK_SIZE>)로 작업 단위를 분할한다.

    Z_DPE_TEST_TAB 테이블의 “ID”컬럼을 기준으로 10,000 건씩 분할하는 chunk를 생성하려면 다음과 같이 실행한다.

    -- 2단계: 작업 단위 분할
    BEGIN
      DBMS_PARALLEL_EXECUTE.CREATE_CHUNKS_BY_NUMBER_COL (
                TASK_NAME    => 'DPE_TEST(BY NUMBER)',
                TABLE_OWNER  => USER,
                TABLE_NAME   => 'Z_DPE_TEST_TAB',
                TABLE_COLUMN => 'ID',
                CHUNK_SIZE   => 10000);
    END;

     

    작업 단위의 분할 상태를 확인해 보자.

    -- 작업 분할 상태 확인
    SELECT *
      FROM USER_PARALLEL_EXECUTE_CHUNKS
     WHERE TASK_NAME = 'DPE_TEST(BY NUMBER)'
     ORDER BY START_ID;

    작업 분할 상태
    작업 분할 상태

     

    위 결과에서 대략적으로 확인할 수 있듯이, 각 Chunk가 10,000개의 Row로 분할되었다. (예제 테이블은 1부터 1백만까지의 순번을 ID값으로 생성했음)

    참고로, ROWID 분할(CREATE_CHUNKS_BY_ROWID procedure) 했을 때는 START_ROWID, END_ROWID에 값이 생성되고, NUMBER Column 분할(CREATE_CHUNKS_BY_NUMBER_COL)했을 때는 START_ID, END_ID에 값이 생성된다.

    작업 단위(chunk)가 균등하게 잘 배분되었는지 확인해 보자.

    -- 작업 분할 균등 확인
    -- Chunk의 START_ID, END_ID range로 추출한 Row Count
    SELECT  B.CHUNK_ID, COUNT(A.ID) ROW_COUNT
      FROM  Z_DPE_TEST_TAB A,
            (
            SELECT  CHUNK_ID, START_ID, END_ID
              FROM  USER_PARALLEL_EXECUTE_CHUNKS
             WHERE  TASK_NAME = 'DPE_TEST(BY NUMBER)'
            ) B
     WHERE  A.ID BETWEEN B.START_ID AND B.END_ID
     GROUP  BY B.CHUNK_ID
     ORDER  BY B.CHUNK_ID;

    작업 분할 균등 확인
    작업 분할 균등 확인

    각 chunk의 START_ID와 END_ID로 테이블의 건수를 확인해 보면 10,000 건으로 잘 분할되어 있다.

    -- Chunk의 START_ID, END_ID range로 추출한 Row 전체 Count
    SELECT  SUM(COUNT(A.ID)) ROW_COUNT
      FROM  Z_DPE_TEST_TAB A,
            (
            SELECT  CHUNK_ID, START_ID, END_ID
              FROM  USER_PARALLEL_EXECUTE_CHUNKS
             WHERE  TASK_NAME = 'DPE_TEST(BY NUMBER)'
            ) B
     WHERE  A.ID BETWEEN B.START_ID AND B.END_ID
    GROUP  BY B.CHUNK_ID;

    chunk row count 합계 확인
    chunk row count 합계 확인

    전체 Chunk의 Row Count의 합계는 1,000,000 으로 전체 데이터 건수와 일치한다.

     

     

     

    3.3. 작업 실행

    RUN_TASK(<TASK_NAME>, <SQL_STMT>, <LANGUAGE_FLAG>, <PARALLEL_LEVEL>)로 작업을 실행한다. 작업 실행 방법은 ROWID 방식과 동일하다.

    -- 3단계: 작업 실행
    DECLARE
      L_SQL_STMT VARCHAR2(32767);
    BEGIN
      L_SQL_STMT := 'UPDATE  Z_DPE_TEST_TAB
                        SET  VAL = ROUND(DBMS_RANDOM.VALUE(1,10000))
                            ,AUDSID = SYS_CONTEXT(''USERENV'',''SESSIONID'')
                      WHERE  ID BETWEEN :START_ID AND :END_ID';
    
      DBMS_PARALLEL_EXECUTE.RUN_TASK(TASK_NAME      => 'DPE_TEST(BY NUMBER)',
                                     SQL_STMT       => L_SQL_STMT,
                                     LANGUAGE_FLAG  => DBMS_SQL.NATIVE,
                                     PARALLEL_LEVEL => 10);
    END;
    /

    실행하는 SQL은 ROWID 분할 사례와 거의 동일하나 WHERE 절의 조건 컬럼이 “ROWID”가 아니라 지정한 NUMBER 컬럼인 “ID” 인 것이 다르다.

    실행 중에 Chunk 상태변화를 살펴보자.

    -- Chunk 상태별 Count
    SELECT STATUS, COUNT
      FROM USER_PARALLEL_EXECUTE_CHUNKS
     WHERE TASK_NAME = 'DPE_TEST(BY NUMBER)'
    GROUP BY STATUS;

     

    작업이 진행중일 때는 다음과 같이 chunk의 상태가 UNASSIGNED -> ASSIGNED -> PROCESSED 로 변경되면서 처리된다.

    작업 실행중 chunk 상태 확인
    작업 실행중 chunk 상태 확인

     

    작업이 완료되면 모든 chunk의 상태가 PROCESSED로 나타난다.

    작업 완료 chunk 상태 확인
    작업 완료 chunk 상태 확인

     

    작업 완료후에 다음 SQL을 실행해 보면 몇 개의 Session에서 몇 개의 행을 update했는지 확인할 수 있다.

    -- 동시 실행현황 확인
    SELECT AUDSID, COUNT(*)
      FROM Z_DPE_TEST_TAB
     GROUP BY AUDSID
     ORDER BY AUDSID;

    세션별 처리한 데이터 건수 확인
    세션별 처리한 데이터 건수 확인

    위 내용에서 다음을 알 수 있다.

    • 총 10개의 Job Session이 실행되었음
    • 각 Job Session은 1만건의 Chunk를 대부분 10개씩 할당 받아 실행하였음
    • AUDSID: 71767 Job Session은 Chunk 9개(9만건)를 할당 받아 실행했고, AUDSID: 71773 Job Session은 Chunk 11개(11만건)를 할당 받아 실행하였음
    • 즉, 전체 Chunk 개수(여기서는 100개)보다 RUN_TASK의 <PARALLEL_LEVEL>이 적을 때 한 Job이 여러 Chunk를 할당 받아서 실행하며, 그 실행 횟수는 Chunk의 분할 정도가 균일하더라도 차이가 있을 수 있음

     

    3.4. 작업 완료 확인 및 삭제

    DROP_TASK(<TASK_NAME>)로 작업을 삭제한다.

    -- 4단계: 작업 완료 확인 및 작업 삭제
    -- 작업 완료 확인
    SELECT * FROM USER_PARALLEL_EXECUTE_TASKS;
    
    -- 작업 삭제
    BEGIN
      DBMS_PARALLEL_EXECUTE.DROP_TASK(TASK_NAME => 'DPE_TEST(BY NUMBER)');
    END;
    /

    작업 완료 확인
    작업 완료 확인


    여기까지 NUMBER Column에 의한 분할 방식의 사례를 살펴보았다. 다음은 사용자 정의 SQL 기반으로 분할하는 사례를 살펴본다.

    댓글

    💲 추천 글