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

88줄짜리 「상품별 마지막 판매」 리포트가 열 때마다 TEMP를 38MB 쓴다

중급SELECT유통366 / 700

상황 ​

본사 상품팀은 단종 후보를 고를 때 「상품별 마지막 판매」(상품마다 마지막으로 팔린 판매번호, 수량, 단가)를 본다. 오전 회의 전에 상품팀 8명이 몰아서 여는데 한 번에 2.3초가 걸리고, DBA에게는 TEMP 사용 경보가 온다. SQL 위에는 2021년에 남긴 메모가 있다. "GROUP BY로 MAX를 구해 다시 조인하면 판매상품을 두 번 읽는다. 분석 함수로 한 번만 읽게 고쳤다."

테이블과 인덱스 ​

  • CF11 판매상품: 1,096,708행 · 8,204블록 · SLE_NO VARCHAR2(15) '20231231-0612'(판매일 + 그날 일련번호, 판매 순서대로 매겨진다) · ITM_NO · SLE_QTY · SLE_UPRC · 판매번호 순서대로 적재
  • CF11_PK (SLE_NO, ITM_NO): BLEVEL 2 · 리프 약 4,290블록 · 다른 인덱스는 없다 · 통계 최신
  • 팔린 상품은 88종이다. 한 판매에 같은 상품은 한 줄뿐이라(PK) 상품 하나 안에서 SLE_NO는 겹치지 않는다
  • 오전에는 다른 배치와 겹쳐 work area 하나의 상한이 약 20MB다

원본 SQL ​

sql
SELECT ITM_NO, SLE_NO, SLE_QTY, SLE_UPRC
  FROM (SELECT d.ITM_NO, d.SLE_NO, d.SLE_QTY, d.SLE_UPRC,
               MAX(d.SLE_NO) OVER (PARTITION BY d.ITM_NO) AS LAST_NO
          FROM CF11 d)
 WHERE SLE_NO = LAST_NO
 ORDER BY ITM_NO

실행계획 학습용 예시 · 메모리 크기는 교재 09화 규모 ​

xplan
----------------------------------------------------------------------------------------------------------------------
| Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem | Used-Mem | Used-Tmp|
----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |      1 |        |     88 |00:00:02.31 |    8204 |       |          |         |
|*  1 |  VIEW               |      |      1 |   1096K|     88 |00:00:02.31 |    8204 |       |          |         |
|   2 |   WINDOW SORT       |      |      1 |   1096K|   1096K|00:00:02.12 |    8204 |    47M|   20M (1)|      38M|
|   3 |    TABLE ACCESS FULL| CF11 |      1 |   1096K|   1096K|00:00:00.13 |    8204 |       |          |         |
----------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("SLE_NO"="LAST_NO")

문제 ​

  1. 88줄을 내는 SQL이 TEMP를 38MB 쓰는 까닭을 실행계획 2번 줄과 MAX() OVER의 성질로 설명하시오.
  2. ROW_NUMBER로 고친 안과, GROUP BY로 상품별 마지막 판매번호를 구해 다시 찾는 안의 일량을 어림해 비교하고, 하나를 골라 SQL로 쓰시오.
  3. 2021년 메모의 "두 번 읽는다"는 판단이 이 테이블에서 맞지 않는 까닭을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자