Skip to content
튜닝 연습인덱스 사용 조건
IDX-059

고객 이름이나 주문번호 하나만 넣는 통합 검색이 고객과 주문을 다 읽고 해시 조인한다

실전SELECT한빛유통59 / 700

상황 ​

고객센터 「통합 검색」은 상담원이 고객 이름이나 주문번호 가운데 아는 것 하나를 넣으면 주문을 고객 정보와 함께 보여 준다. 처음에는 주문번호 칸만 있었는데, 고객 이름 칸을 더하면서 두 조건을 OR로 이었다. 상담원 40명이 하루 약 1만 2천 번 쓴다. 한 번에 926블록이라 하루 1,100만 블록이 넘는다. 박팀장은 "OR를 없애는 방법을 두세 개 놓고, 결과가 틀릴 위험과 운영 부담까지 비교해 와라"고 했다.

테이블과 인덱스 ​

  • T_ORD 주문: 100,000행 · 896블록 · ORD_SEQ(PK) · CUS_ID(고객당 약 50건, 테이블 곳곳에 흩어져 있다) · ORD_DT · ORD_ST · PAY_TP · PAY_DT · ORD_AMT
  • M_CUS 고객: 2,000행 · 30블록 · CUS_ID(PK) · CUS_NM(동명이인이 있다, 한 이름에 1 ~ 3명) · RGN_ID
  • 인덱스 PK_T_ORD (ORD_SEQ) · IX_T_ORD_CUS (CUS_ID) · PK_M_CUS (CUS_ID) · IX_M_CUS_NM (CUS_NM) · 모두 BLEVEL 1 · 통계 최신
  • 화면은 넣지 않은 칸을 NULL로 넘긴다

원본 SQL ​

sql
SELECT o.ORD_SEQ, o.ORD_DT, o.ORD_ST, o.PAY_TP, o.PAY_DT, o.ORD_AMT, c.CUS_ID, c.CUS_NM, c.RGN_ID
  FROM T_ORD o, M_CUS c
 WHERE c.CUS_ID = o.CUS_ID
   AND (c.CUS_NM = :v_nm OR o.ORD_SEQ = :v_ord)
 ORDER BY o.ORD_DT DESC

실행계획 학습용 예시 ​

xplan
[고객 이름 하나(동명이인 2명, 주문 100건)를 넣었을 때 · 주문번호만 넣어도 계획은 같다(1건, Buffers 926)]
-----------------------------------------------------------------------------------------
| Id  | Operation            | Name  | Starts | E-Rows | A-Rows | A-Time      | Buffers |
-----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |       |      1 |        |    100 | 00:00:00.03 |     926 |
|   1 |  SORT ORDER BY       |       |      1 |   1051 |    100 | 00:00:00.03 |     926 |
|*  2 |   HASH JOIN          |       |      1 |   1051 |    100 | 00:00:00.03 |     926 |
|   3 |    TABLE ACCESS FULL | M_CUS |      1 |   2000 |   2000 | 00:00:00.01 |      30 |
|   4 |    TABLE ACCESS FULL | T_ORD |      1 |   100K |   100K | 00:00:00.02 |     896 |
-----------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("C"."CUS_ID"="O"."CUS_ID")
       filter(("C"."CUS_NM"=:V_NM OR "O"."ORD_SEQ"=:V_ORD))

문제 ​

  1. 인덱스가 다 있는데도 두 테이블을 다 읽고 해시 조인한 뒤에야 거르는 이유를 OR의 두 갈래가 걸린 테이블로 설명하시오.
  2. ① 갈래마다 드라이빙 테이블이 다른 UNION ALL로 손수 나누기 ② USE_CONCAT 같은 힌트로 옵티마이저에게 펼치게 하기 ③ 화면에서 검색 칸마다 SQL을 따로 부르기를 결과의 정확성(겹치는 행, 정렬)과 운영 부담의 관점에서 비교하시오.
  3. 채택한 방법을 SQL로 작성하고 고친 뒤의 읽는 양을 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자