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

커버링 인덱스로 8블록이면 끝나는 「누적 판매 수량」이 상품 상세 화면에서는 1천 블록을 읽는다

기초SELECT한빛유통212 / 700

상황 ​

상품 상세 화면 상단의 「누적 판매 수량」은 상품 하나가 지금까지 몇 줄, 몇 개 팔렸는지를 보여 준다. 상품 상세가 열릴 때마다 돌아서 하루 3만 번 호출된다. 지난달 오과장이 이 칸을 위해 IX_T_ORD_DET_ITM (ITM_ID, ORD_QTY)를 만들었다. SQL Developer에서 T_ORD_DET를 직접 조회하면 8블록이었는데, 화면에서는 1,029블록을 읽는다. 화면 코드는 사내 표준대로 주문 공통 뷰 V_ORD_DET를 쓴다.

테이블과 인덱스 ​

  • 뷰 V_ORD_DET: T_ORD_DET d JOIN T_ORD o ON o.ORD_SEQ = d.ORD_SEQ · d의 컬럼 전부와 o.CUS_ID, o.ORD_DT, o.ORD_ST를 내보낸다 · 주문 관련 화면 30여 개가 함께 쓴다
  • T_ORD_DET: 200,000행 · 896블록 · PK_T_ORD_DET (ORD_SEQ, ORD_DET_NO) · IX_T_ORD_DET_ITM (ITM_ID, ORD_QTY) · 상품마다 2,000줄(테이블 전체에 흩어져 있다)
  • T_ORD: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ)(리프 약 220블록)
  • 신 시스템에는 FK가 하나도 없다(교재 01화) · 지금 데이터에서 주문 헤더가 없는 주문상세는 0건 · 통계 최신

원본 SQL ​

sql
SELECT COUNT(*) AS det_cnt, SUM(ORD_QTY) AS sale_qty
  FROM V_ORD_DET
 WHERE ITM_ID = :v_itm

실행계획 학습용 예시 ​

xplan
----------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                               | Name             | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  Used-Mem |
----------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                        |                  |      1 |        |      1 |00:00:00.02 |    1029 |           |
|   1 |  SORT AGGREGATE                         |                  |      1 |      1 |      1 |00:00:00.02 |    1029 |           |
|*  2 |   HASH JOIN                             |                  |      1 |   2000 |   2000 |00:00:00.02 |    1029 | 1599K (0) |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED  | T_ORD_DET        |      1 |   2000 |   2000 |00:00:00.01 |     806 |           |
|*  4 |     INDEX RANGE SCAN                    | IX_T_ORD_DET_ITM |      1 |   2000 |   2000 |00:00:00.01 |       8 |           |
|   5 |    INDEX FAST FULL SCAN                 | PK_T_ORD         |      1 |   100K |   100K |00:00:00.01 |     223 |           |
----------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("O"."ORD_SEQ"="D"."ORD_SEQ")
   4 - access("D"."ITM_ID"=:V_ITM)

문제 ​

  1. 결과에 T_ORD의 컬럼을 하나도 쓰지 않는데 5번 줄에 PK_T_ORD가 나오는 이유와, 커버링 인덱스를 만들었는데도 3번 줄에서 테이블을 읽는 이유를 설명하시오.
  2. 이 화면이 인덱스만 읽고 끝나도록 고치시오. 뷰를 쓰는 다른 화면에도 효과가 있는 방법을 쓰고, 그 방법을 적용하기 전에 확인할 것을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자