Skip to content
튜닝 연습소트 튜닝과 페이징
SORT-039

고객 등급 재산정 배치가 작업 테이블을 채우다 ORA-01652로 멈췄다

기초INSERT한빛유통344 / 700

상황 ​

야간 배치 「고객 등급 재산정」의 1단계는 최근 2년 주문을 작업 테이블 W_ORD_GD로 옮기고, 2단계는 그 테이블을 고객별로 묶어 등급을 매긴다. 지난밤 1단계가 ORA-01652: unable to extend temp segment by 128 in tablespace TEMP로 멈췄다. 같은 시각에 다른 큰 배치 둘이 TEMP를 쓰고 있었다. 배치 담당 오과장은 TEMP 테이블스페이스를 늘리자고 한다. 1단계 SQL의 ORDER BY 옆에는 -- 고객순으로 넣어야 2단계가 빠르다 (2017.03 강도현)라는 주석이 있다. 2단계는 2021년에 PL/SQL 루프에서 GROUP BY 한 문장으로 바뀌었다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · 2023-01-01 이후 주문은 666,964행이다
  • W_ORD_GD(작업 테이블, 이 문제용): CUS_ID · ORD_DT · ORD_AMT · ORD_ST · 배치를 시작할 때 TRUNCATE · 인덱스 없음 · 2단계 말고는 아무도 읽지 않는다
  • 2단계 SQL: SELECT CUS_ID, COUNT(*), SUM(ORD_AMT) FROM W_ORD_GD WHERE ORD_ST = 'COMPLETE' GROUP BY CUS_ID(HASH GROUP BY, 고객 2,000명)
  • 02시의 work area 상한(global memory bound)은 약 20MB이고, TEMP 테이블스페이스 4GB를 세 배치가 나눠 쓴다. 통계는 최신이다.

원본 SQL ​

sql
INSERT /*+ APPEND */ INTO W_ORD_GD (CUS_ID, ORD_DT, ORD_AMT, ORD_ST)
SELECT CUS_ID, ORD_DT, ORD_AMT, ORD_ST
  FROM T_ORD_BIG
 WHERE ORD_DT >= DATE '2023-01-01'
 ORDER BY CUS_ID, ORD_DT        -- 고객순으로 넣어야 2단계가 빠르다 (2017.03 강도현)

실행계획 학습용 예시 ​

xplan
[그저께 밤 · 성공한 실행]
----------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem | Used-Tmp|
----------------------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                 |           |      1 |        |      0 |00:00:09.84 |    6136 |       |       |          |         |
|   1 |  LOAD AS SELECT                  | W_ORD_GD  |      1 |        |      0 |00:00:09.84 |    6136 |       |       |          |         |
|   2 |   OPTIMIZER STATISTICS GATHERING |           |      1 |    667K|    667K|00:00:07.95 |    5839 |       |       |          |         |
|   3 |    SORT ORDER BY                 |           |      1 |    667K|    667K|00:00:07.71 |    5839 |    31M|  1820K|   20M (1)|      29M|
|*  4 |     TABLE ACCESS FULL            | T_ORD_BIG |      1 |    667K|    667K|00:00:00.21 |    5826 |       |       |          |         |
----------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - filter("ORD_DT">=TO_DATE(' 2023-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

[지난밤]  ORA-01652 · 3번 줄이 정렬 묶음(run)을 TEMP에 내려놓다가 실패 · 그 시각 TEMP 사용 3.98GB / 4GB(다른 배치 둘이 3.95GB)

문제 ​

  1. 1단계가 TEMP를 쓰는 까닭을 실행계획 3번 줄로 설명하고, 그 정렬이 지금의 2단계에 쓸모가 있는지 판단하시오.
  2. 2단계에 같은 결과를 넘기면서 1단계가 TEMP를 쓰지 않도록 고치고, TEMP를 늘리자는 안과 비교해 무엇이 다른지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자