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

주문 뒤 10분 안의 적립을 찾는 점검이 포인트 테이블을 583번 읽는다

기초SELECT이커머스172 / 700

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

상황 ​

마케팅팀의 「적립 지연 점검」은 한 달 치 주문마다, 같은 고객에게 주문 뒤 10분 안에 들어온 적립(EARN) 거래를 붙여 본다. 화면은 이 목록과 주문 수를 비교해 적립이 늦거나 빠진 주문을 따로 띄운다. 포인트 거래에는 주문 번호가 없어서 고객과 시각으로 짝을 짓는다. SQL 위에는 -- 기간(부등호) 조건 조인은 해시 조인이 안 된다. NL 로 고정이라는 주석이 있다. 담당자가 기간을 바꿔 가며 하루 수십 번 돌린다. 아래는 2024년 6월(주문 583건)의 실행계획이다.

테이블과 인덱스 ​

  • orders: 34,908행 · 193블록 · PK(order_id)만 있음 · order_date 시분초 있음 · 2024년 6월 583건
  • point_transactions: 45,000행 · 210블록 · PK(tx_id)만 있음 · tx_type EARN 15,000건 · USE · EXPIRE · created_at 시분초 있음
  • 두 테이블 모두 customer_id에 인덱스가 없다 (FK는 꺼져 있다) · 통계 최신

원본 SQL ​

sql
SELECT /*+ LEADING(o p) USE_NL(p) */
       o.order_id, o.customer_id, o.order_date, p.tx_id, p.amount, p.created_at
  FROM orders o, point_transactions p
 WHERE o.order_date >= TO_DATE(:v_from, 'YYYYMMDD')
   AND o.order_date <  TO_DATE(:v_to, 'YYYYMMDD')
   AND p.customer_id = o.customer_id
   AND p.tx_type     = 'EARN'
   AND p.created_at >= o.order_date
   AND p.created_at <  o.order_date + 10/1440

실행계획 학습용 예시 ​

xplan
-----------------------------------------------------------------------------------------------------
| Id  | Operation           | Name               | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-----------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                    |      1 |        |    521 |00:00:00.38 |    122K |
|*  1 |  FILTER             |                    |      1 |        |    521 |00:00:00.38 |    122K |
|   2 |   NESTED LOOPS      |                    |      1 |      2 |    521 |00:00:00.38 |    122K |
|*  3 |    TABLE ACCESS FULL| ORDERS             |      1 |    573 |    583 |00:00:00.01 |     193 |
|*  4 |    TABLE ACCESS FULL| POINT_TRANSACTIONS |    583 |      1 |    521 |00:00:00.37 |    122K |
-----------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(TO_DATE(:V_TO,'YYYYMMDD')>TO_DATE(:V_FROM,'YYYYMMDD'))
   3 - filter(("O"."ORDER_DATE">=TO_DATE(:V_FROM,'YYYYMMDD') AND "O"."ORDER_DATE"<TO_DATE(:V_TO,'YYYYMMDD')))
   4 - filter(("P"."CUSTOMER_ID"="O"."CUSTOMER_ID" AND "P"."TX_TYPE"='EARN' AND "P"."CREATED_AT">="O"."ORDER_DATE"
              AND "P"."CREATED_AT"<"O"."ORDER_DATE"+.006944444444444444444444444444444444444444))

문제 ​

  1. 122K 블록이 어디서 나오는지 4번 줄의 Starts와 블록 수로 설명하시오.
  2. 주석의 "부등호 조건 조인은 해시 조인이 안 된다"가 이 SQL에 맞는 말인지 판단하고, 개선 SQL을 작성하시오. 개선 후 Predicate Information에서 각 조건이 어디에 쓰이는지도 서술하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자