Skip to content
튜닝 연습서브쿼리와 쿼리 변환
SUBQ-015

매장 여섯 줄짜리 판매 현황이 판매 테이블을 여섯 번 통째로 읽는다

기초SELECT유통250 / 700

상황 ​

본사 상황판의 「매장별 이번 달 판매 건수」는 매장 6곳(본사 포함)의 판매 건수를 보여 주고 5분마다 새로 고친다. 한 번에 0.2초지만 하루 288번 돌면서 판매 테이블을 통째로 1,728번 읽는다. 아래는 2023년 6월 치다.

테이블과 인덱스 ​

  • CF07 매장: 6행 · 4블록 · CF07_PK (SHP_NO) · 본사(1000)는 판매하지 않는다
  • CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) 말고는 인덱스가 없다 · 2023년 6월 20,953건(매장 1001 ~ 1005가 4,157 ~ 4,234건씩)
  • 판매는 하루 600 ~ 800건 들어온다 · 통계 최신

원본 SQL ​

sql
SELECT f.SHP_NO, f.SHP_NM,
       (SELECT COUNT(*)
          FROM CF10 h
         WHERE h.SHP_NO = f.SHP_NO
           AND h.SLE_DT BETWEEN '20230601' AND '20230630') AS sle_cnt
  FROM CF07 f
 ORDER BY f.SHP_NO

실행계획 학습용 예시 · 건수는 적재 데이터 그대로 ​

xplan
------------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |      1 |        |      6 |00:00:00.21 |   27502 |
|   1 |  SORT AGGREGATE    |      |      6 |      1 |      6 |00:00:00.21 |   27498 |
|*  2 |   TABLE ACCESS FULL| CF10 |      6 |   4110 |  20953 |00:00:00.21 |   27498 |
|   3 |  SORT ORDER BY     |      |      1 |      6 |      6 |00:00:00.21 |   27502 |
|   4 |   TABLE ACCESS FULL| CF07 |      1 |      6 |      6 |00:00:00.01 |       4 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(("H"."SLE_DT">='20230601' AND "H"."SLE_DT"<='20230630' AND "H"."SHP_NO"=:B1))

문제 ​

  1. 2번 줄의 Starts와 Buffers로 이 SQL이 판매 테이블을 어떻게 읽는지 설명하시오. 스칼라 서브쿼리 캐시가 여기서 도움이 되지 않는 이유도 쓰시오.
  2. 본사가 0건으로 나오는 결과를 그대로 두고 SQL이나 인덱스를 고치시오. 인덱스를 만드는 안과 판매를 한 번만 읽는 안을 비교하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자