3. NUMBER列分区法并行处理案例(DBMS_PARALLEL_EXECUTE)

让我们看一下使用 Oracle DBMS_PARALLEL_EXECUTE 进行 NUMBER 列分区方法并行处理的情况。包括任务创建、工作单元划分、任务执行、任务完成确认、删除等。

这是上一篇文章的延续。

2.5.工作单元拆分细节检查(DBMS_PARALLEL_EXECUTE)

3. NUMBER列拆分法并行处理案例

让我们看一下按 NUMBER 列除法的示例。它与 ROWID 方法几乎相似,但以下几项略有不同。

  • 划分工作单元时使用 CREATE_CHUNKS_BY_NUMBER_COL 过程。
  • 执行任务时,在 SQL 语句的 WHERE 子句中使用 NUMBER 列。

* 参考Oracle文档: DBMS_PARALLEL_EXECUTE – CREATE_CHUNKS_BY_NUMBER_COL 过程

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( ,

,
,
, )划分工作单位。

要根据 Z_DPE_TEST_TAB 表的“ID”列创建分为 10,000 个事例的块,请执行以下操作。

-- 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;
작업 분할 상태
工作分割状态

从上面的结果可以大致看出,每个块被分为 10,000 行。 (示例表是使用 1 到 100 万的连续数字创建的 ID 值)

作为参考,当划分 ROWID(CREATE_CHUNKS_BY_ROWID 过程)时,会在 START_ROWID 和 END_ROWID 中创建值,而当划分 NUMBER 列(CREATE_CHUNKS_BY_NUMBER_COL)时,会在 START_ID 和 END_ID 中创建值。

让我们检查一下工作单元(块)是否分布均匀。

-- 작업 분할 균등 확인
-- 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;
작업 분할 균등 확인
检查平等分工

如果您使用每个块的 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 합계 확인
检查块行计数总和

所有块的总行数为 1,000,000,与数据总数相匹配。

3.3.作业运行

运行任务( , , , )来执行任务。任务执行方式与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”而是“ID”,即指定的NUMBER列。

让我们看看执行过程中块状态的变化。

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

当工作正在进行时,块的状态更改为 UNASSIGNED -> ASSIGNED -> PROCESSED 并按如下方式处理。

작업 실행중 chunk 상태 확인
任务运行时检查块状态

任务完成后,所有块的状态均显示为“已处理”。

작업 완료 chunk 상태 확인
检查任务完成块状态

完成任务后,您可以通过执行以下SQL来检查哪些会话中更新了多少行。

-- 동시 실행현황 확인
SELECT AUDSID, COUNT(*)
  FROM Z_DPE_TEST_TAB
 GROUP BY AUDSID
 ORDER BY AUDSID;
세션별 처리한 데이터 건수 확인
检查每个会话处理的数据数量

从以上内容我们可以看出:

  • 总共执行了 10 个作业会话。
  • 每个作业会话执行时分配了 10,000 个块,大部分为每个块 10 个。
  • AUDSID: 71767 作业会话被分配了 9 个块(90,000 个案例)来执行,而 AUDSID: 71773 作业会话被分配并被执行了 11 个块(110,000 个案例)。
  • 换句话说,RUN_TASK的数量大于chunk的总数(这里是100)。当这个值很小时,一个作业会被分配多个块并执行,即使块的划分程度是均匀的,执行次数也可能会有所不同。

3.4.确认任务完成并删除

删除任务( ) 删除任务。

-- 4단계: 작업 완료 확인 및 작업 삭제
-- 작업 완료 확인
SELECT * FROM USER_PARALLEL_EXECUTE_TASKS;

-- 작업 삭제
BEGIN
  DBMS_PARALLEL_EXECUTE.DROP_TASK(TASK_NAME => 'DPE_TEST(BY NUMBER)');
END;
/
작업 완료 확인
确认任务完成

到目前为止,我们已经了解了使用 NUMBER 列划分方法进行并行处理的示例。接下来,我们看一个基于用户定义SQL的分区示例。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注