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

매장 200줄이어야 할 「매장별 월 주문 건수」 표가 50만 줄로 내려와 엑셀이 멈춘다

기초SELECT버거368 / 700

상황 ​

버거 본사 재무팀이 「2013년 매장별 월 주문 건수」(매장마다 한 줄, 1월 ~ 12월 열두 칸)를 요청했다. 조민우가 PIVOT으로 만들어 넘겼는데, 내려받기가 6초 넘게 걸리고 TEMP를 100MB 넘게 쓴다. 엑셀에는 50만 줄이 들어왔고, 줄마다 열두 칸 가운데 한 칸만 1이고 나머지는 0이다. 조민우는 "PIVOT은 FOR 뒤의 월로 칸을 나누고 나머지는 알아서 묶어 주니까 매장별로 묶일 줄 알았다"라고 한다.

테이블과 인덱스 ​

  • ORD 주문: 1,000,000행 · 22,422블록 · ORD_NO(PK) · ORD_DT VARCHAR2(8) · ORD_HMS VARCHAR2(6) · SHOP_NO 200곳 · 문자열 채움 컬럼(행 약 195바이트)
  • 2013년 주문은 500,212행(테이블의 절반)이다
  • 인덱스 ORD_PK (ORD_NO) · ORD_X01 (ORD_DT, ORD_HMS) · 통계 최신
  • 내려받기는 낮에 돌고, 그 시간 work area 하나의 상한은 약 20MB다

원본 SQL ​

sql
SELECT *
  FROM (SELECT o.*, SUBSTR(o.ORD_DT, 5, 2) AS MM
          FROM ORD o
         WHERE o.ORD_DT BETWEEN '20130101' AND '20131231')
 PIVOT (COUNT(*) FOR MM IN ('01' AS M01, '02' AS M02, '03' AS M03, '04' AS M04,
                           '05' AS M05, '06' AS M06, '07' AS M07, '08' AS M08,
                           '09' AS M09, '10' AS M10, '11' AS M11, '12' AS M12))
 ORDER BY SHOP_NO

실행계획 학습용 예시 ​

xplan
---------------------------------------------------------------------------------------------------------------------
| Id  | Operation             | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem | Used-Mem | Used-Tmp|
---------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |      |      1 |        |    500K|00:00:06.37 |   22422 |       |          |         |
|   1 |  SORT ORDER BY        |      |      1 |    500K|    500K|00:00:06.37 |   22422 |   118M|   21M (1)|     104M|
|   2 |   HASH GROUP BY PIVOT |      |      1 |    500K|    500K|00:00:04.12 |   22422 |   131M|   21M (1)|     112M|
|*  3 |    TABLE ACCESS FULL  | ORD  |      1 |    500K|    500K|00:00:00.21 |   22422 |       |          |         |
---------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter(("O"."ORD_DT">='20130101' AND "O"."ORD_DT"<='20131231'))

[엑셀에 들어온 결과 · 앞의 세 줄]
  ORD_NO   ORD_DT    ORD_HMS  SHOP_NO  (채움 컬럼 …)  M01 M02 M03 … M12
  500213   20130101  000012   SH0131                   1   0   0  …  0
  500214   20130101  000107   SH0007                   1   0   0  …  0

문제 ​

  1. 매장 200줄을 기대한 표가 500,212줄로 나온 까닭을 PIVOT이 묶는 기준으로 설명하시오.
  2. 매장 한 줄에 열두 달이 나오도록 SQL을 고치고, 고친 뒤 실행계획에서 무엇이 줄고 무엇이 그대로인지 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자