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

하루 스무 건 출고 목록이 6천 블록을 읽는다

기초SELECT이커머스152 / 700

이 문제는 교재 18화 졸업 과제와 같은 이커머스 데이터베이스를 씁니다. 『튜너의 1년』을 순서대로 읽고 있다면 졸업 과제를 먼저 풀고 오세요. 아래 「테이블과 인덱스」 칸에 과제의 답 일부(제약 조건, 인덱스, 통계의 실제 상태)가 나옵니다.

상황 ​

물류센터의 「출고 지시서」는 그날 들어온 주문의 상품 목록을 주문번호 순으로 뽑는다. 창고 단말 30대가 수시로 다시 뽑아서 하루 1만 2천 번 호출된다. 이 SQL은 구 쇼핑몰에서 옮겨 왔고, 맨 위의 힌트도 그대로 가져왔다. 개발자는 "구 시스템에서는 0.01초였다"라고 말한다.

테이블과 인덱스 ​

  • orders: 34,908행 · 193블록 · 인덱스는 PK_ORDERS (order_id)뿐 · order_date는 DATE(시분초 있음) · 하루 평균 19건 (아래 실행계획은 2024-06-14, 21건)
  • order_items: 73,498행 · 290블록 · 인덱스는 PK_ORDER_ITEMS (order_item_id)뿐 · 주문당 평균 2.1줄
  • FK order_items.order_id → orders는 정의만 있고 꺼져 있다 (DISABLED NOT VALIDATED) · order_id에 인덱스 없음
  • 구 쇼핑몰에는 order_items(order_id) 인덱스가 있었다 · 통계 최신

원본 SQL ​

sql
SELECT /*+ LEADING(o i) USE_NL(i) */
       o.order_id, o.order_date, i.product_id, i.quantity
  FROM orders o, order_items i
 WHERE o.order_date >= TO_DATE(:d, 'YYYYMMDD')
   AND o.order_date <  TO_DATE(:d, 'YYYYMMDD') + 1
   AND i.order_id = o.order_id
 ORDER BY o.order_id, i.product_id

실행계획 학습용 예시 ​

xplan
-------------------------------------------------------------------------------------------
| Id  | Operation            | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |      1 |        |     44 |00:00:00.03 |    6283 |
|   1 |  SORT ORDER BY       |             |      1 |     40 |     44 |00:00:00.03 |    6283 |
|*  2 |   FILTER             |             |      1 |        |     44 |00:00:00.03 |    6283 |
|   3 |    NESTED LOOPS      |             |      1 |     40 |     44 |00:00:00.03 |    6283 |
|*  4 |     TABLE ACCESS FULL| ORDERS      |      1 |     19 |     21 |00:00:00.01 |     193 |
|*  5 |     TABLE ACCESS FULL| ORDER_ITEMS |     21 |      2 |     44 |00:00:00.03 |    6090 |
-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(TO_DATE(:D,'YYYYMMDD')+1>TO_DATE(:D,'YYYYMMDD'))
   4 - filter(("O"."ORDER_DATE">=TO_DATE(:D,'YYYYMMDD') AND "O"."ORDER_DATE"<TO_DATE(:D,'YYYYMMDD')+1))
   5 - filter("I"."ORDER_ID"="O"."ORDER_ID")

문제 ​

  1. 6,283블록 중 6,090블록이 어디서 나오는지 Starts와 블록 수로 설명하시오. Predicate Information 5번 줄에서 무엇을 알 수 있는지도 설명하시오.
  2. 개선안을 SQL(DDL 포함)로 작성하고, 구 시스템에서는 이 힌트가 왜 옳았는지와 지금은 무엇이 달라졌는지 서술하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자