Skip to content
튜닝 연습소트 튜닝과 페이징
SORT-038

「이 상품을 산 주문」 목록에서 같은 날 같은 금액으로 두 번 산 주문이 한 줄로 보인다

중급SELECT이커머스343 / 700

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

상황 ​

관리자 화면의 상품 상세에는 「이 상품을 산 주문」 목록(주문일, 고객 이름, 주문 금액, 상태)이 최근 주문부터 나온다. 고객센터에 이런 문의가 들어왔다. "선물용으로 같은 날 같은 상품을 두 번 따로 주문했는데 관리자 화면에는 한 줄만 있다." 주문 테이블에는 두 주문이 다 있다. 개발자는 한 주문에 같은 상품이 옵션별로 두 줄 담기면 목록에 같은 주문이 두 번 나와서 DISTINCT를 붙였다고 한다.

테이블과 인덱스 ​

  • order_items: 73,498행 · 290블록 · order_item_id(PK) · order_id · product_id · quantity · unit_price
  • orders: 34,908행 · 193블록 · order_id(PK) · customer_id · order_date DATE(시분초 있음) · status · total_amount
  • customers: 5,230행 · 51블록 · customer_id(PK) · name
  • 인덱스는 세 테이블 모두 PK뿐이다. 상품 105가 담긴 주문상품 줄은 266줄이고 주문은 259건이다(7건은 같은 상품이 두 줄). 통계는 최신이다.

원본 SQL ​

sql
SELECT DISTINCT TRUNC(o.order_date) AS order_day, c.name, o.total_amount, o.status
  FROM order_items i, orders o, customers c
 WHERE i.product_id = :prod
   AND o.order_id = i.order_id
   AND c.customer_id = o.customer_id
 ORDER BY order_day DESC

실행계획 학습용 예시 ​

xplan
[상품 105]
---------------------------------------------------------------------------------------------------------------------------
| Id  | Operation           | Name        | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
---------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |             |      1 |        |    256 |00:00:00.02 |     534 |       |       |          |
|   1 |  SORT UNIQUE        |             |      1 |    262 |    256 |00:00:00.02 |     534 | 30720 | 30720 |27648  (0)|
|*  2 |   HASH JOIN         |             |      1 |    262 |    266 |00:00:00.02 |     534 |  1250K|  1250K| 1340K (0)|
|*  3 |    HASH JOIN        |             |      1 |    262 |    266 |00:00:00.01 |     483 |  1316K|  1316K| 1428K (0)|
|*  4 |     TABLE ACCESS FULL| ORDER_ITEMS |      1 |    262 |    266 |00:00:00.01 |     290 |       |       |          |
|   5 |     TABLE ACCESS FULL| ORDERS      |      1 |  34908 |  34908 |00:00:00.01 |     193 |       |       |          |
|   6 |    TABLE ACCESS FULL | CUSTOMERS   |      1 |   5230 |   5230 |00:00:00.01 |      51 |       |       |          |
---------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("C"."CUSTOMER_ID"="O"."CUSTOMER_ID")
   3 - access("O"."ORDER_ID"="I"."ORDER_ID")
   4 - filter("I"."PRODUCT_ID"=:PROD)

[대조 · 상품 105]  주문상품 266줄 · 주문 259건 · 화면 256줄

문제 ​

  1. 주문상품 266줄, 주문 259건, 화면 256줄의 차이를 각각 무엇이 만들었는지 SQL과 실행계획으로 설명하시오.
  2. 주문이 빠지지도 겹치지도 않도록 SQL을 고치고, 고친 SQL에서 중복 제거(SORT UNIQUE)가 왜 필요 없는지 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자