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

결과 세 줄짜리 「고객 등급별 매출」 화면이 0.8초 걸리고 블록을 100만 개 넘게 읽는다

중급SELECT한빛유통151 / 700

상황 ​

「고객 등급별 매출」 화면이 0.8초 걸린다. 소스 맨 위에는 -- 건드리지 말 것 (2018.11)이라는 주석이 있고, 그때 회의록에는 "조인 방식을 USE_NL로 고정 · 3초 → 0.4초"라고 적혀 있다. 회의록 첨부 문서의 마지막 줄은 "측정 조건: 운영 DB 복제본, 주문 20,000건"이다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 (인덱스 없음)
  • M_CUS: 2,000행 · 30블록 · PK_M_CUS (CUS_ID) · CUS_GD 분포 A 1% · B 9% · C 90%
  • M_RGN: 8행 · PK_M_RGN (RGN_ID)

원본 SQL ​

sql
SELECT /*+ LEADING(o c) USE_NL(c) */
       c.CUS_GD, COUNT(*) AS ord_cnt, SUM(o.ORD_AMT) AS amt,
       MAX((SELECT r.RGN_NM FROM M_RGN r WHERE r.RGN_ID = c.RGN_ID)) AS rgn_sample
  FROM T_ORD_BIG o, M_CUS c
 WHERE c.CUS_ID = o.CUS_ID
 GROUP BY c.CUS_GD

실행계획 실측 · 교재 06화 ​

xplan
Plan hash value: 2289018667

---------------------------------------------------------------------------------------------
| Id  | Operation                     | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |           |      1 |        |      3 |00:00:00.77 |    1026K|
|   1 |  TABLE ACCESS BY INDEX ROWID  | M_RGN     |      8 |      1 |      8 |00:00:00.01 |      12 |
|*  2 |   INDEX UNIQUE SCAN           | PK_M_RGN  |      8 |      1 |      8 |00:00:00.01 |       4 |
|   3 |  HASH GROUP BY                |           |      1 |      3 |      3 |00:00:00.77 |    1026K|
|   4 |   NESTED LOOPS                |           |      1 |   1000K|   1000K|00:00:00.64 |    1026K|
|   5 |    NESTED LOOPS               |           |      1 |   1000K|   1000K|00:00:00.31 |   26837 |
|   6 |     TABLE ACCESS FULL         | T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.04 |    5826 |
|*  7 |     INDEX UNIQUE SCAN         | PK_M_CUS  |   1000K|      1 |   1000K|00:00:00.15 |   21011 |
|   8 |    TABLE ACCESS BY INDEX ROWID| M_CUS     |   1000K|      1 |   1000K|00:00:00.21 |    1000K|
---------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("R"."RGN_ID"=:B1)
   7 - access("C"."CUS_ID"="O"."CUS_ID")

문제 ​

  1. 1,026K 블록이 어디서 나오는지 실행계획의 Starts로 설명하시오. 2018년에는 이 힌트가 왜 옳았는지도 설명하시오.
  2. 개선안을 SQL로 작성하고, 이 규모에서 그 조인 방식이 맞는 이유를 서술하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자