Skip to content
튜닝 연습인덱스 스캔 효율과 테이블 액세스
ACC-044

고객 12개월 추이를 보려고 월 실적 테이블의 PK를 열두 달 치 다 훑는다

중급SELECT한빛유통119 / 700

상황 ​

고객센터 상담 화면에는 「고객 12개월 추이」가 있다. 상담원이 고객을 열면 최근 12개월의 월별 주문 건수와 금액을 띄운다. 하루 2,000번쯤 열린다. 데이터는 마감 배치가 매달 초 T_ORD_BIG에서 고객별로 집계해 넣는 월 실적 테이블에서 온다. 조민우는 (CUS_ID, ORD_YM) 인덱스를 하나 더 만들자고 했다. 배치 담당 오과장은 이렇게 답했다. "월 마감 배치가 쓰는 테이블의 인덱스는 늘리기 싫다. 지금 있는 걸로 안 되나?"

테이블과 인덱스 ​

  • T_CUS_MON 고객 월 실적(T_ORD_BIG의 파생 테이블, 이 문제에서 정의): ORD_YM VARCHAR2(6) · CUS_ID · ORD_CNT · ORD_AMT · 2022-01 ~ 2024-12의 36개월 × 고객 2,000명 = 72,000행 · 320블록 · 매달 초 한 달 치 2,000행을 CUS_ID 순으로 덧붙인다
  • 인덱스 PK_T_CUS_MON (ORD_YM, CUS_ID): BLEVEL 1 · 리프 약 266블록(리프 한 블록에 약 270항목, 한 달 2,000항목이 리프 약 7.4블록) · 통계 최신
  • 다른 인덱스는 없다 · 「월 고객 순위」 화면(ORD_YM = :ym)도 PK를 쓴다

원본 SQL ​

sql
SELECT ORD_YM, ORD_CNT, ORD_AMT
  FROM T_CUS_MON
 WHERE CUS_ID = :v_cus
   AND ORD_YM BETWEEN :v_ym_from AND :v_ym_to
 ORDER BY ORD_YM

실행계획 학습용 예시 · T_CUS_MON은 T_ORD_BIG에서 집계한 파생 테이블(이 문제에서 정의) ​

xplan
---------------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
---------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |      1 |        |     12 |00:00:00.01 |     103 |
|*  1 |  FILTER                      |              |      1 |        |     12 |00:00:00.01 |     103 |
|   2 |   TABLE ACCESS BY INDEX ROWID| T_CUS_MON    |      1 |     12 |     12 |00:00:00.01 |     103 |
|*  3 |    INDEX RANGE SCAN          | PK_T_CUS_MON |      1 |     12 |     12 |00:00:00.01 |      91 |
---------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(:V_YM_FROM<=:V_YM_TO)
   3 - access("ORD_YM">=:V_YM_FROM AND "CUS_ID"=:V_CUS AND "ORD_YM"<=:V_YM_TO)
       filter("CUS_ID"=:V_CUS)

문제 ​

  1. 3번 줄이 91블록을 읽는 이유를 access와 filter로 설명하시오.
  2. 인덱스를 새로 만들지 않고 읽는 양을 줄이도록 SQL을 고치시오. 그 방법이 여기서 효과가 있는 이유를 선두 컬럼의 분포로 설명하시오.
  3. 조민우 안 (CUS_ID, ORD_YM)과 Buffers, 적재 비용을 비교해 어느 쪽을 고를지 판단하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자