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

고객 요약 팝업에 '총 주문 금액' 칸 하나를 더했더니 4블록이던 조회가 500블록을 넘는다

기초SELECT한빛유통96 / 700

상황 ​

고객센터의 「고객 요약」 팝업은 고객 번호를 넣으면 그 고객의 주문 건수를 보여 준다. 상담원 서른 명이 하루 6천 번쯤 연다. 이번 달 요청으로 팝업에 '총 주문 금액' 칸을 더해 SUM(ORD_AMT)가 SQL에 들어갔다. 배포 다음 날부터 팝업이 굼뜨다는 말이 나왔다. 개발자는 "조건은 그대로 CUS_ID 하나라서 같은 인덱스를 타는데요"라고 한다. 아래는 고객 CUS_000123이다.

테이블과 인덱스 ​

  • T_ORD_BIG: 1,000,000행 · 5,826블록(블록당 약 172행) · ORD_SEQ 순으로 쌓였다 · CUS_ID 2,000명, 고객당 500건 · 한 고객의 주문은 ORD_SEQ 2,000건 간격으로 나온다
  • 인덱스 IX_ORD_BIG_CUS (CUS_ID): BLEVEL 2 · 리프 약 3,060블록(리프 한 블록에 약 327항목) · CLUSTERING_FACTOR 약 1,000,000 · 이 팝업만 쓴다 · 통계 최신
  • 다른 인덱스: IX_ORD_BIG_DT (ORD_DT) · 주문은 운영에서 계속 INSERT된다

원본 SQL ​

sql
SELECT COUNT(*) AS ord_cnt, SUM(ORD_AMT) AS ord_amt
  FROM T_ORD_BIG
 WHERE CUS_ID = :v_cus

실행계획 학습용 예시 · 건수는 적재 스크립트 그대로 ​

xplan
[지난달: 건수만 셀 때]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |      1 |00:00:00.01 |       4 |
|   1 |  SORT AGGREGATE                      |                |      1 |      1 |      1 |00:00:00.01 |       4 |
|*  2 |   INDEX RANGE SCAN                   | IX_ORD_BIG_CUS |      1 |    500 |    500 |00:00:00.01 |       4 |
----------------------------------------------------------------------------------------------------------------
   2 - access("CUS_ID"=:V_CUS)

[지금: 합계 칸을 더한 뒤]
----------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name           | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
----------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |                |      1 |        |      1 |00:00:00.01 |     504 |
|   1 |  SORT AGGREGATE                      |                |      1 |      1 |      1 |00:00:00.01 |     504 |
|   2 |   TABLE ACCESS BY INDEX ROWID BATCHED| T_ORD_BIG      |      1 |    500 |    500 |00:00:00.01 |     504 |
|*  3 |    INDEX RANGE SCAN                  | IX_ORD_BIG_CUS |      1 |    500 |    500 |00:00:00.01 |       4 |
----------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - access("CUS_ID"=:V_CUS)

문제 ​

  1. 같은 인덱스를 타는데 Buffers가 4에서 504로 늘어난 이유를 두 실행계획의 차이와 CLUSTERING_FACTOR로 설명하시오.
  2. 팝업이 다시 테이블을 읽지 않도록 인덱스를 고치고 DDL을 작성하시오. 기존 인덱스를 어떻게 할지와 그 대가도 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자