Skip to content
튜닝 연습파티션
PART-049

해시 8칸으로 나눈 두 분석 테이블을 병렬로 조인하는데 주문상품 247만 행이 서버 사이를 오간다

중급SELECT버거424 / 700

상황 ​

버거 본사 데이터팀은 병렬 분석용으로 주문과 주문상품의 복사본을 해시 8칸으로 나눠 두었다. 분기마다 「전 기간 매장별 메뉴 판매」를 DOP 8로 돌리는데 12초 가까이 걸린다. 계획을 본 선배: "둘 다 8칸이면 칸끼리 짝지어 조인할 텐데, PX SEND가 왜 있지?" 데이터팀은 주문상품을 나눌 때 "PK 컬럼으로 나눠야 고르게 퍼진다"며 PK 두 컬럼을 해시 키로 썼다.

테이블과 인덱스 ​

  • ORD_H 주문(분석 복사본, 문제 설정): ORD 1,000,000행을 PARTITION BY HASH (ORD_NO) PARTITIONS 8로 CTAS했다. 칸 하나는 약 125,000행이고 8칸 전체는 약 22,510블록이다.
  • ORD_ITEM_H 주문상품(분석 복사본, 문제 설정): ORD_ITEM 2,472,717행을 PARTITION BY HASH (ORD_NO, ITEM_ID) PARTITIONS 8로 CTAS했다. 8칸 전체는 약 55,384블록이다.
  • 매장 200개 × 상품 92개라서 결과는 18,400행이다. 인덱스는 없다.
  • 분석 DB는 EE이고 병렬 실행이 켜져 있다(parallel_max_servers 32). 이 시각에 다른 병렬 작업은 없다. 통계는 최신이다.

원본 SQL ​

sql
SELECT /*+ PARALLEL(8) */
       o.SHOP_NO, i.ITEM_ID, SUM(i.ORD_ITEM_QTY) AS qty, COUNT(*) AS line_cnt
  FROM ORD_H o, ORD_ITEM_H i
 WHERE i.ORD_NO = o.ORD_NO
 GROUP BY o.SHOP_NO, i.ITEM_ID

실행계획 학습용 예시 · 병렬 계획은 EE 모양(교재 14화 §9.3) · FORMAT => 'ALLSTATS ALL' ​

xplan
---------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name       | Starts | A-Rows | Buffers | Used-Mem | Pstart | Pstop |    TQ  |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                 |            |      1 |  18400 |   77894 |          |        |       |        |      |            |
|   1 |  PX COORDINATOR                  |            |      1 |  18400 |   77894 |          |        |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)            | :TQ10002   |      8 |  18400 |   77894 |          |        |       |  Q1,02 | P->S | QC (RAND)  |
|   3 |    HASH GROUP BY                 |            |      8 |  18400 |   77894 |    1124K |        |       |  Q1,02 | PCWP |            |
|   4 |     PX RECEIVE                   |            |      8 |   147K |   77894 |          |        |       |  Q1,02 | PCWP |            |
|   5 |      PX SEND HASH                | :TQ10001   |      8 |   147K |   77894 |          |        |       |  Q1,01 | P->P | HASH       |
|   6 |       HASH GROUP BY              |            |      8 |   147K |   77894 |    1610K |        |       |  Q1,01 | PCWP |            |
|*  7 |        HASH JOIN                 |            |      8 |  2472K |   77894 |    5120K |        |       |  Q1,01 | PCWP |            |
|   8 |         PX PARTITION HASH ALL    |            |      8 |  1000K |   22510 |          |      1 |     8 |  Q1,01 | PCWC |            |
|   9 |          TABLE ACCESS FULL       | ORD_H      |      8 |  1000K |   22510 |          |      1 |     8 |  Q1,01 | PCWP |            |
|  10 |         PX RECEIVE               |            |      8 |  2472K |   55384 |          |        |       |  Q1,01 | PCWP |            |
|  11 |          PX SEND PARTITION (KEY) | :TQ10000   |      8 |  2472K |   55384 |          |        |       |  Q1,00 | P->P | PART (KEY) |
|  12 |           PX BLOCK ITERATOR      |            |      8 |  2472K |   55384 |          |      1 |     8 |  Q1,00 | PCWC |            |
|  13 |            TABLE ACCESS FULL     | ORD_ITEM_H |    104 |  2472K |   55384 |          |      1 |     8 |  Q1,00 | PCWP |            |
---------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   7 - access("I"."ORD_NO"="O"."ORD_NO")

[V$PQ_TQSTAT · 한 번 실행]
  TQ_ID  SERVER_TYPE  서버 수  NUM_ROWS 합계
  0      Producer     8        2,472,717    (주문상품 전부를 ORD_H 의 칸 기준으로 다시 나눠 보냈다)
  1      Producer     8          147,200    (서버마다 부분 집계)
  2      Producer     8           18,400
  경과 11.8초 · PX 서버 대기 1위 PX Deq Credit: send blkd

문제 ​

  1. 실행계획의 어느 줄에서 주문상품 행이 서버 사이를 오가는지 줄 번호와 PQ Distrib로 쓰고, 주문 쪽은 왜 옮기지 않는지 설명하시오.
  2. 행을 주고받지 않고 칸끼리 조인하게 하려면 무엇을 바꿔야 하는지 DDL로 작성하고, 바뀐 계획의 모양을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자