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

DW로 넘기는 「판매 흐름」 추출이 정렬을 네 번 하고, 정렬마다 TEMP를 27MB씩 쓴다

실전INSERT유통361 / 700

상황 ​

본사 DW 연동 배치는 매일 02시에 2년 치 판매 전체를 작업 테이블 W_SLE_FLOW로 옮기면서 판매마다 네 가지 값을 붙인다. 그날 매장 안의 판매 순번, 그날 매장 판매 수, 마감까지 남은 판매 수, 같은 날 직전 판매의 시각이다. DW는 이 표를 통째로 가져가 자기 테이블에 다시 정렬해 싣는다. 이 단계만 9초 가까이 걸리고 TEMP를 100MB 넘게 쓴다. 회의에 세 안이 올라왔다. ㉠ DBA는 이 세션만 정렬 메모리를 크게 잡자고 한다. ㉡ 개발팀은 (SHP_NO, SLE_DT, SLE_NO) 인덱스를 만들어 정렬을 없애자고 한다. ㉢ 정렬 기준을 맞춰 정렬 횟수를 줄이자는 안도 있다. 오과장은 "세 안을 숫자와 부작용으로 비교해서 하나를 골라 달라"고 했다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · SLE_NO VARCHAR2(15)는 판매일자와 그날의 순번으로 매겨('20231231-0612') 판매번호 순서가 곧 시각 순서다 · SHP_NO 매장 6곳 · SLE_DT · SLE_HMS · SLE_DOW
  • SLE_HMS는 33,241건이 앞자리 0 없이 들어 있다('93015'는 09시 30분 15초). 교정은 승인됐지만 다음 달 정기 점검 때 적용된다(교재 03화, 09화).
  • 테이블은 판매번호 순으로 쌓여 있다. 한 매장의 하루 판매(약 114건)는 그날 판매가 든 블록 6 ~ 7개에 흩어져 있다.
  • W_SLE_FLOW는 배치가 비우고(TRUNCATE) 직접 경로로 채운다. 02시에는 다른 배치들도 돌아 정렬 하나가 받는 작업 공간이 작다. 통계는 최신이다.

원본 SQL ​

sql
TRUNCATE TABLE W_SLE_FLOW;

INSERT /*+ APPEND */ INTO W_SLE_FLOW
       (SLE_NO, SHP_NO, SLE_DT, SLE_HMS, DAY_SEQ, DAY_CNT, LEFT_CNT, PREV_HMS)
SELECT SLE_NO, SHP_NO, SLE_DT, SLE_HMS,
       ROW_NUMBER() OVER (PARTITION BY SHP_NO, SLE_DT ORDER BY SLE_NO)          AS day_seq,
       COUNT(*)     OVER (PARTITION BY SHP_NO, SLE_DT)                          AS day_cnt,
       ROW_NUMBER() OVER (PARTITION BY SHP_NO, SLE_DT ORDER BY SLE_NO DESC) - 1 AS left_cnt,
       LAG(SLE_HMS) OVER (PARTITION BY SHP_NO, SLE_DT ORDER BY SLE_HMS)         AS prev_hms
  FROM CF10
 ORDER BY SLE_NO;                  -- DW 가 판매번호 순으로 받으면 빠를 것 같아서 (2016)
COMMIT;

실행계획 학습용 예시 ​

xplan
-------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                        | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads | Writes | Used-Mem | Used-Tmp |
-------------------------------------------------------------------------------------------------------------------------------------------
|   0 | INSERT STATEMENT                 |            |      1 |        |      0 |00:00:08.94 |    4701 | 13604 |  15712 |          |          |
|   1 |  LOAD AS SELECT                  | W_SLE_FLOW |      1 |        |      0 |00:00:08.94 |    4701 | 13604 |  15712 |          |          |
|   2 |   OPTIMIZER STATISTICS GATHERING |            |      1 |    500K|    500K|00:00:08.31 |    4583 | 13604 |  13604 |  256K    |          |
|   3 |    SORT ORDER BY                 |            |      1 |    500K|    500K|00:00:08.12 |    4583 | 13604 |  13604 | 2190K (1)|      27M |
|   4 |     WINDOW SORT                  |            |      1 |    500K|    500K|00:00:06.20 |    4583 | 10203 |  10203 | 2190K (1)|      27M |
|   5 |      WINDOW SORT                 |            |      1 |    500K|    500K|00:00:04.21 |    4583 |  6802 |   6802 | 2190K (1)|      27M |
|   6 |       WINDOW SORT                |            |      1 |    500K|    500K|00:00:02.18 |    4583 |  3401 |   3401 | 2190K (1)|      27M |
|   7 |        TABLE ACCESS FULL         | CF10       |      1 |    500K|    500K|00:00:00.06 |    4583 |     0 |      0 |          |          |
-------------------------------------------------------------------------------------------------------------------------------------------

문제 ​

  1. 정렬이 왜 네 번인지 분석 함수의 정렬 기준으로 설명하고, 9초가 어디서 나오는지 쓰시오.
  2. ㉠, ㉡, ㉢을 일량과 부작용으로 비교해 하나를 고르시오.
  3. 고른 안으로 SQL을 고치시오. 직전 판매 시각이 지금 결과와 달라진다면 어느 쪽이 맞는지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자