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

가격 구간이 겹치는지 보는 아침 점검이 820블록을 읽는 데 7초 가까이 걸린다

기초SELECT한빛유통200 / 700

상황 ​

한빛유통은 최저가 연동 배치가 매일 04시에 상품마다 그날 판매가를 정하고 가격 이력에 새 구간을 연다. 지난달 배치가 재처리되면서 같은 날 구간이 두 번 들어간 상품이 생겼고, 그 상품의 주문은 반품 화면에서 두 줄로 보였다. 그래서 데이터팀이 매일 06시에 겹친 구간을 찾는 점검을 넣었다. 결과는 몇 줄뿐인데 매번 7초 가까이 걸리고, 같은 시각에 도는 정산 배치를 밀어낸다. 조민우는 "읽는 블록이 820개뿐이라 더 줄일 데가 없다"라고 한다.

테이블과 인덱스 ​

  • T_ITM_PRC_LOG 상품 판매가 이력 (이 문제에서 쓰는 파생 테이블, 선분이력): ITM_ID · ST_DTM (구간 시작, DATE) · ED_DTM (다음 구간의 시작 시각, 이 시각 미만까지) · SLE_PRC
  • 2023-01-01부터 날마다 상품 100개에 한 구간씩: 73,106행 · 410블록 · 상품마다 약 731행 · 지금 구간의 ED_DTM은 DATE '9999-12-31'
  • 인덱스 IX_ITM_PRC_LOG (ITM_ID, ST_DTM): PK나 유니크가 아닌 일반 인덱스라서 같은 시작 시각이 두 번 들어가도 막지 못한다 · 통계 최신
  • 지난달 재처리로 상품 6개의 2024-10-21 구간이 한 번 더 들어가 있다

원본 SQL ​

sql
SELECT a.ITM_ID, a.ST_DTM, a.ED_DTM, b.ST_DTM AS ST_DTM2, b.ED_DTM AS ED_DTM2
  FROM T_ITM_PRC_LOG a, T_ITM_PRC_LOG b
 WHERE b.ITM_ID = a.ITM_ID
   AND b.ROWID <> a.ROWID
   AND b.ST_DTM < a.ED_DTM
   AND a.ST_DTM < b.ED_DTM

실행계획 학습용 예시 ​

xplan
-------------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name          | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  Used-Mem |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |               |      1 |        |     12 |00:00:06.84 |     820 |           |
|*  1 |  HASH JOIN         |               |      1 |    133K|     12 |00:00:06.84 |     820 | 4318K (0) |
|   2 |   TABLE ACCESS FULL| T_ITM_PRC_LOG |      1 |  73106 |  73106 |00:00:00.01 |     410 |           |
|   3 |   TABLE ACCESS FULL| T_ITM_PRC_LOG |      1 |  73106 |  73106 |00:00:00.01 |     410 |           |
-------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - access("B"."ITM_ID"="A"."ITM_ID")
       filter(("B"."ST_DTM"<"A"."ED_DTM" AND "A"."ST_DTM"<"B"."ED_DTM" AND "B".ROWID<>"A".ROWID))

[결과]  12행 (상품 6개의 겹친 구간 6쌍이 앞뒤를 바꿔 두 번씩)  ·  CPU used by this session 6.71초

문제 ​

  1. 테이블을 두 번 한 번씩만 읽었는데(820블록) 7초 가까이 걸리는 까닭을 해시 조인의 build와 probe로 설명하시오.
  2. 같은 상품의 구간을 시작 시각 순으로 늘어놓았을 때 무엇만 비교하면 되는지 생각해, 테이블을 한 번 읽는 점검 SQL로 고치시오. 구간이 끊긴 곳(빈 시간)도 함께 찾도록 하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자