Skip to content
튜닝 연습조인 튜닝
JOIN-026

시즌 메뉴 한 가지의 매장 · 요일 판매를 보는데 판매 50만 건을 메모리에 올린다

중급SELECT유통176 / 700

상황 ​

상품팀의 「상품 판매 분포」는 상품 하나를 고르면 2년 치 판매를 매장과 요일로 나눠 보여 준다. 시즌 메뉴를 검토하는 회의 전에 상품을 바꿔 가며 돌리고, 매장 다섯 곳의 점장도 아침마다 연다. 개발팀 코딩 규칙에 "헤더 → 상세 순서로 조인한다"가 있어서 판매 헤더부터 읽도록 힌트가 붙어 있다. 아침 9시 무렵 여러 명이 함께 열면 PGA 사용량이 수백 MB로 뛴다는 DBA 보고가 있었다. 아래는 시즌 메뉴(ITM_NO = 1047) 하나로 조회한 실행계획이다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) · SHP_NO 5곳 · SLE_DOW 1 ~ 7
  • CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · ITM_NO만으로 찾는 인덱스는 없다 · ITM_NO = 1047은 2년 동안 8,512줄이다
  • 통계 최신 · 히스토그램 없음 (옵티마이저는 상품 하나를 1,096,708 / 88 ≈ 12,463줄로 본다)

원본 SQL ​

sql
SELECT /*+ LEADING(a b) USE_HASH(b) */
       a.SHP_NO, a.SLE_DOW, COUNT(*) AS sle_lines, SUM(b.SLE_QTY) AS sle_qty
  FROM CF10 a, CF11 b
 WHERE b.ITM_NO = :v_itm
   AND b.SLE_NO = a.SLE_NO
 GROUP BY a.SHP_NO, a.SLE_DOW

실행계획 학습용 예시 ​

xplan
--------------------------------------------------------------------------------------------------------------
| Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |      |      1 |        |     35 |00:00:00.31 |   12787 |       |       |          |
|   1 |  HASH GROUP BY      |      |      1 |     35 |     35 |00:00:00.31 |   12787 |  1200K|  1200K|  961K (0)|
|*  2 |   HASH JOIN         |      |      1 |  12463 |   8512 |00:00:00.30 |   12787 |    29M|  4671K|   33M (0)|
|   3 |    TABLE ACCESS FULL| CF10 |      1 |    500K|    500K|00:00:00.04 |    4583 |       |       |          |
|*  4 |    TABLE ACCESS FULL| CF11 |      1 |  12463 |   8512 |00:00:00.07 |    8204 |       |       |          |
--------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("B"."SLE_NO"="A"."SLE_NO")
   4 - filter("B"."ITM_NO"=:V_ITM)

문제 ​

  1. 2번 줄 해시 조인의 build가 무엇이고 몇 행인지, 그래서 메모리를 얼마나 쓰는지 설명하시오. 코딩 규칙 "헤더 → 상세"가 해시 조인의 build 선택에도 맞는 기준인지 판단하시오.
  2. build가 작은 집합이 되도록 SQL을 고치고, NL 조인(CF11 → CF10_PK)으로 바꾸는 안과 Buffers를 비교하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자