Skip to content
튜닝 연습서브쿼리와 쿼리 변환
SUBQ-001

고객 2,000명만 확인하면 되는 점검이 고객 마스터를 75만 번 찾아간다

실전SELECT한빛유통236 / 700

상황 ​

정산 화면 상단의 「고객 미확인 주문」 배지는 주문 원장의 고객번호가 고객 마스터에 없는(고객명이 붙지 않는) 주문이 몇 건인지 보여 준다. 정산 담당자 10명이 화면을 열 때마다 돌아서 하루 약 300번 실행되고, 한 번에 0.47초 걸린다. 이 SQL을 짠 조민우는 "고객은 2,000명뿐이니 스칼라 서브쿼리면 캐시돼서 2,000번만 간다. 06화의 지역명도 Starts 8이었다"라고 했다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록 · CUS_ID 2,000종류가 정확히 500번씩 돌아가며 들어 있다 (CUS_000001, CUS_000002, … 순서)
  • M_CUS: 2,000행 · 30블록 · PK_M_CUS (CUS_ID)
  • 한빛유통 신 시스템은 FK가 0개라 주문의 고객번호가 마스터에 있다는 보장이 없다 (지금 고아는 0건)
  • 통계 최신 · _query_execution_cache_max_size는 기본값 (131,072바이트)

원본 SQL ​

sql
SELECT COUNT(*)  AS ord_cnt,
       COUNT(nm) AS named_cnt,          -- ord_cnt - named_cnt = 고객 미확인 주문
       MAX(nm)   AS nm_sample
  FROM (SELECT (SELECT c.CUS_NM FROM M_CUS c WHERE c.CUS_ID = o.CUS_ID) AS nm
          FROM T_ORD_BIG o)

실행계획 실측 · 교재 07 · 08화 ​

xplan
---------------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |      1 |        |      1 |00:00:00.47 |     779K|
|   1 |  TABLE ACCESS BY INDEX ROWID| M_CUS     |    752K|      1 |    752K|00:00:00.32 |     774K|
|*  2 |   INDEX UNIQUE SCAN         | PK_M_CUS  |    752K|      1 |    752K|00:00:00.12 |   21011 |
|   3 |  SORT AGGREGATE             |           |      1 |      1 |      1 |00:00:00.47 |     779K|
|   4 |   TABLE ACCESS FULL         | T_ORD_BIG |      1 |   1000K|   1000K|00:00:00.05 |    5826 |
---------------------------------------------------------------------------------------------

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

(DBMS_XPLAN 이 줄여 쓴 값 — 752K = 752,995 · 779K = 779,832 · 774K = 774,006)

문제 ​

  1. 1번과 2번 줄의 Starts 752,995가 어떻게 나왔는지 설명하시오. 개발자가 예상한 2,000과 왜 다른지, 06화의 지역명 스칼라 서브쿼리는 왜 Starts가 8이었는지도 설명하시오.
  2. 같은 답을 내는 조인으로 바꾸시오. 이 점검의 목적에 비추어 내부 조인과 외부 조인 중 무엇이어야 하는지, 바꾸기 전에 무엇을 증명해야 하는지 쓰시오.
  3. M_CUS에 PK가 없어 같은 고객번호가 두 줄이라면 스칼라 서브쿼리와 조인이 각각 어떻게 되는지 설명하시오. 스칼라 서브쿼리를 그대로 두는 편이 나은 경우가 있다면 언제인지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자