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

전 매장 오늘 현황판이 1분마다 오늘 주문 범위를 200번 다시 읽는다

중급SELECT버거189 / 700

상황 ​

본사 상황실의 「전 매장 오늘 현황」은 매장 200곳의 오늘 주문 건수와 마지막 주문 시각을 1분마다 새로 띄운다(영업시간 14시간 동안 하루 840번). 주문이 없는 매장도 0으로 보여야 해서 아우터 조인으로 썼다. 개발자는 "NL 조인이니 오늘 주문 1,400건을 하나씩 읽으면서 매장을 붙일 줄 알았다"라고 한다. 아래는 2013-06-14 밤 9시에 뜬 실행계획이다.

테이블과 인덱스 ​

  • SHOP 매장: 200행 · 5블록 · PK (SHOP_NO)
  • ORD 주문: 1,000,000행 · 22,422블록 · 하루 약 1,370건
  • 인덱스 ORD_X01 (ORD_DT, ORD_HMS): 날짜순 적재, CF 22,223 · 하루치는 인덱스 리프 약 6블록, 테이블 약 31블록
  • SHOP_NO로 시작하는 인덱스는 없다 · 2013-06-14 주문 1,368건 · 그날 주문이 없는 매장 3곳(리모델링) · 통계 최신

원본 SQL ​

sql
SELECT /*+ USE_NL(o) */           -- 주문은 NL 로 붙인다 (오늘 주문부터 읽게)
       s.SHOP_NO, s.SHOP_NM,
       COUNT(o.ORD_NO) AS ord_cnt,
       MAX(o.ORD_HMS)  AS last_hms
  FROM SHOP s, ORD o
 WHERE o.SHOP_NO(+) = s.SHOP_NO
   AND o.ORD_DT(+)  = :v_dt
 GROUP BY s.SHOP_NO, s.SHOP_NM
 ORDER BY s.SHOP_NO

실행계획 학습용 예시 ​

xplan
-----------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |         |      1 |        |    200 |00:00:00.19 |    7609 |
|   1 |  SORT GROUP BY                        |         |      1 |    200 |    200 |00:00:00.19 |    7609 |
|   2 |   NESTED LOOPS OUTER                  |         |      1 |   1370 |   1371 |00:00:00.18 |    7609 |
|   3 |    TABLE ACCESS FULL                  | SHOP    |      1 |    200 |    200 |00:00:00.01 |       7 |
|*  4 |    TABLE ACCESS BY INDEX ROWID BATCHED| ORD     |    200 |      7 |   1368 |00:00:00.17 |    7602 |
|*  5 |     INDEX RANGE SCAN                  | ORD_X01 |    200 |   1370 |    274K|00:00:00.04 |    1200 |
-----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - filter("O"."SHOP_NO"(+)="S"."SHOP_NO")
   5 - access("O"."ORD_DT"(+)=:V_DT)

문제 ​

  1. 개발자의 기대와 달리 어느 테이블이 드라이빙이 됐는지 계획에서 찾고, 아우터 조인을 NL로 처리할 때 순서가 왜 그렇게 정해지는지 설명하시오.
  2. 7,609블록이 어디서 나오는지 4번 줄과 5번 줄의 Starts와 A-Rows로 설명하시오.
  3. 개선 SQL을 작성하고, ORD (SHOP_NO, ORD_DT) 인덱스를 만들어 NL을 유지하는 안과 숫자로 비교하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자