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

매장 이름과 주소 두 칸을 붙이는 데 매장 테이블을 1만 4천 번 찾는다

기초SELECT버거243 / 700

상황 ​

본사 영업관리팀은 매달 1일에 지난달 주문 전체를 엑셀로 내려받는다(주문번호, 일시, 매장명, 매장 주소). 2013년 12월 치 42,408건을 내려받을 때 읽은 블록의 대부분이 매장 테이블이다. 개발자는 "매장은 200곳뿐이라 스칼라 서브쿼리 캐시가 다 기억한다. 칸이 두 개라 서브쿼리도 두 개 썼다"라고 했다.

테이블과 인덱스 ​

  • ORD: 1,000,000행 · 22,422블록 · ORD_DT VARCHAR2(8) · 날짜순으로 쌓여 있다 · 2013년 12월 42,408건 · SHOP_NO 200종류가 고르게 섞여 있다(매장마다 약 212건)
  • ORD_X01 (ORD_DT, ORD_HMS): CF 22,223(좋음) · 한 달 치 리프 약 140블록
  • SHOP: 200행 · 5블록 · SHOP_PK (SHOP_NO) · SHOP_NM · ADDR
  • 통계 최신

원본 SQL ​

sql
SELECT o.ORD_NO, o.ORD_DT, o.ORD_HMS, o.SHOP_NO,
       (SELECT s.SHOP_NM FROM SHOP s WHERE s.SHOP_NO = o.SHOP_NO) AS shop_nm,
       (SELECT s.ADDR    FROM SHOP s WHERE s.SHOP_NO = o.SHOP_NO) AS shop_addr
  FROM ORD o
 WHERE o.ORD_DT BETWEEN '20131201' AND '20131231'
 ORDER BY o.ORD_DT, o.ORD_HMS

실행계획 학습용 예시 ​

xplan
--------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |         |      1 |        |  42408 |00:00:00.21 |   30570 |
|   1 |  TABLE ACCESS BY INDEX ROWID | SHOP    |   7374 |      1 |   7374 |00:00:00.03 |   14748 |
|*  2 |   INDEX UNIQUE SCAN          | SHOP_PK |   7374 |      1 |   7374 |00:00:00.01 |    7374 |
|   3 |  TABLE ACCESS BY INDEX ROWID | SHOP    |   7374 |      1 |   7374 |00:00:00.03 |   14748 |
|*  4 |   INDEX UNIQUE SCAN          | SHOP_PK |   7374 |      1 |   7374 |00:00:00.01 |    7374 |
|   5 |  TABLE ACCESS BY INDEX ROWID | ORD     |      1 |  42408 |  42408 |00:00:00.21 |   30570 |
|*  6 |   INDEX RANGE SCAN           | ORD_X01 |      1 |  42408 |  42408 |00:00:00.01 |     142 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("S"."SHOP_NO"=:B1)
   4 - access("S"."SHOP_NO"=:B1)
   6 - access("O"."ORD_DT">='20131201' AND "O"."ORD_DT"<='20131231')

문제 ​

  1. 1번과 3번 줄의 Starts가 각각 7,374인 이유를 설명하시오. 매장이 200곳인데 200이 아닌 까닭과 같은 수가 두 번 찍힌 까닭을 함께 쓰시오.
  2. 매장 테이블을 한 번만 읽도록 SQL을 고치시오. NL 조인으로 바꾸면 어떻게 되는지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자