Skip to content
튜닝 연습소트 튜닝과 페이징
SORT-033

상담원 화면의 고객 이름 순서를 바로잡은 다음 날부터 주문 원장 첫 화면이 주문 테이블을 통째로 읽는다

기초SELECT한빛유통338 / 700

상황 ​

고객센터 「고객 찾기」는 고객을 이름순으로 20명씩 보여 준다. 상담원들이 "영문 이름은 대문자와 소문자가 따로 놀고, '(주)'로 시작하는 법인과 한자 이름이 맨 앞에 몰려 있다"고 하자, 개발팀은 지난주 고객센터 WAS의 연결 풀 초기화 SQL에 ALTER SESSION SET NLS_SORT = KOREAN_M 한 줄을 넣었다. 이름 순서는 상담원들이 원하던 대로 바뀌었다. 그다음 날부터 같은 WAS의 「주문 원장」 첫 화면(고객번호순 50건)이 0.01초에서 0.4초로 늘었다. 상담원 200명이 하루 약 1만 번 연다. 개발팀은 "주문 원장 SQL은 한 글자도 바꾸지 않았다"고 한다.

테이블과 인덱스 ​

  • M_CUS 고객: 2,000행 · 30블록 · CUS_NM VARCHAR2 NOT NULL(대부분 한글 이름이고, 영문 이름 37명, 한자 이름 12명, '(주)'로 시작하는 법인 41곳) · 인덱스 IX_M_CUS_NM (CUS_NM)
  • T_ORD_BIG: 1,000,000행 · 5,826블록 · CUS_ID VARCHAR2(40) NOT NULL(모두 'CUS_' + 숫자 여섯 자리) · 인덱스 IX_ORD_BIG_CUS_DT (CUS_ID, ORD_DT): BLEVEL 2 · 리프 약 3,000블록 · 한 고객의 주문은 테이블 곳곳에 흩어져 있다
  • NLS_COMP는 BINARY 그대로다. 통계는 최신이다.

원본 SQL ​

sql
-- 고객센터 WAS 연결 풀 초기화 SQL (지난주 추가)
ALTER SESSION SET NLS_SORT = KOREAN_M;

-- Q1 「고객 찾기」 첫 화면 : 이름순 20명
SELECT CUS_ID, CUS_NM, CUS_GD
  FROM M_CUS
 ORDER BY CUS_NM
 FETCH FIRST 20 ROWS ONLY;

-- Q2 「주문 원장」 첫 화면 : 고객번호순 50건
SELECT CUS_ID, ORD_DT, ORD_SEQ, ORD_AMT
  FROM T_ORD_BIG
 ORDER BY CUS_ID, ORD_DT
 FETCH FIRST 50 ROWS ONLY;

실행계획 학습용 예시 · 정렬 키의 모양(NLSSORT)과 정렬 순서는 교재 환경 23ai에서 확인 ​

xplan
[Q2 · 지난주까지 (세션 NLS_SORT = BINARY)]
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name              | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                   |      1 |        |     50 |00:00:00.01 |      53 |          |
|*  1 |  COUNT STOPKEY                 |                   |      1 |        |     50 |00:00:00.01 |      53 |          |
|   2 |   VIEW                         |                   |      1 |     50 |     50 |00:00:00.01 |      53 |          |
|   3 |    TABLE ACCESS BY INDEX ROWID | T_ORD_BIG         |      1 |   1000K|     50 |00:00:00.01 |      53 |          |
|   4 |     INDEX FULL SCAN            | IX_ORD_BIG_CUS_DT |      1 |     50 |     50 |00:00:00.01 |       3 |          |
------------------------------------------------------------------------------------------------------------------------

[Q2 · 지금 (세션 NLS_SORT = KOREAN_M)]
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name              | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                   |      1 |        |     50 |00:00:00.41 |    5826 |          |
|*  1 |  COUNT STOPKEY                 |                   |      1 |        |     50 |00:00:00.41 |    5826 |          |
|   2 |   VIEW                         |                   |      1 |   1000K|     50 |00:00:00.41 |    5826 |          |
|*  3 |    SORT ORDER BY STOPKEY       |                   |      1 |   1000K|     50 |00:00:00.41 |    5826 | 15360 (0)|
|   4 |     TABLE ACCESS FULL          | T_ORD_BIG         |      1 |   1000K|   1000K|00:00:00.06 |    5826 |          |
------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=50)
   3 - filter(ROWNUM<=50)

Column Projection Information (identified by operation id):
-----------------------------------------------------------
   3 - (#keys=2) NLSSORT("CUS_ID",'nls_sort=''KOREAN_M'''), "ORD_DT", "CUS_ID", "ORD_SEQ", "ORD_AMT"

[Q1 · 지금]  SORT ORDER BY STOPKEY · TABLE ACCESS FULL M_CUS · Buffers 30   (지난주는 INDEX FULL SCAN IX_M_CUS_NM · Buffers 17)

문제 ​

  1. 주문 원장 SQL을 바꾸지 않았는데 실행계획이 인덱스 읽기에서 테이블 전체 읽기와 SORT ORDER BY STOPKEY로 바뀐 까닭을 3번 줄의 정렬 키로 설명하시오.
  2. 상담원이 원하는 이름 순서는 지키면서 주문 원장이 다시 50건만 읽고 멈추도록 고치시오. 고객번호와 고객 이름에 각각 어떤 정렬이 맞는지 근거를 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자