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

매장 하루치 영수증 150장을 펼치는데 판매상품 110만 줄을 다 읽는다

기초SELECT유통158 / 700

상황 ​

매장 관리 화면의 「일별 영수증 상세」는 매장과 날짜를 고르면 그날 영수증마다 판매 상품 줄을 보여 준다. 점장 다섯 명과 본사 영업팀이 하루 2천 번쯤 누른다. 03화에서 SLE_DT 인덱스를 만든 뒤로 판매 헤더 쪽은 빨라졌는데, 이 화면은 여전히 0.1초가 넘는다. SQL은 2009년에 만든 그대로이고, 조인 조건 끝에 주석이 하나 붙어 있다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · CF10_PK (SLE_NO) · IX_CF10_SLE_DT (SLE_DT) (03화에서 만든 인덱스, 하루치가 약 14블록에 모여 있다) · 하루 약 700건 · 판매 매장은 1001 ~ 1005의 5곳
  • CF11 판매상품: 1,096,708행 · 8,204블록 · CF11_PK (SLE_NO, ITM_NO) · 영수증 한 장에 1 ~ 4줄
  • 강남점(SHP_NO = 1001)의 2023-06-01 영수증 150장, 판매 줄 332줄, 금액 2,844,500원 · 통계 최신

원본 SQL ​

sql
SELECT a.SLE_NO, a.SLE_HMS, b.ITM_NO, b.SLE_QTY, b.SLE_UPRC
  FROM CF10 a, CF11 b
 WHERE a.SLE_DT = :v_dt
   AND a.SHP_NO = :v_shp
   AND b.SLE_NO || '' = a.SLE_NO     -- CF11 인덱스 억제, 헤더부터 읽게 (2009.04 RBO)
 ORDER BY a.SLE_NO, b.ITM_NO

실행계획 학습용 예시 · 행 수는 실데이터 ​

xplan
-------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  Used-Mem |
-------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |                |      1 |        |    332 |00:00:00.12 |    8223 |           |
|   1 |  SORT ORDER BY                         |                |      1 |    300 |    332 |00:00:00.12 |    8223 |   34K (0) |
|*  2 |   HASH JOIN                            |                |      1 |    300 |    332 |00:00:00.12 |    8223 | 1243K (0) |
|*  3 |    TABLE ACCESS BY INDEX ROWID BATCHED | CF10           |      1 |    137 |    150 |00:00:00.01 |      19 |           |
|*  4 |     INDEX RANGE SCAN                   | IX_CF10_SLE_DT |      1 |    685 |    706 |00:00:00.01 |       5 |           |
|   5 |    TABLE ACCESS FULL                   | CF11           |      1 |  1096K |  1096K |00:00:00.05 |    8204 |           |
-------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("A"."SLE_NO"="B"."SLE_NO"||'')
   3 - filter("A"."SHP_NO"=:V_SHP)
   4 - access("A"."SLE_DT"=:V_DT)

문제 ​

  1. Predicate Information 2번 줄을 보고, 영수증 150장의 판매 줄을 찾는 데 왜 CF11을 처음부터 끝까지 읽는지 설명하시오.
  2. 결과가 바뀌지 않게 SQL을 고쳐 영수증마다 CF11_PK로 판매 줄을 찾아가도록 하시오. 2009년의 주석이 왜 붙었는지와 지금은 왜 필요 없는지도 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자