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

고객 상세의 「최근 주문 10건」에 어제 주문이 없다, 날짜순으로 줄은 서 있는데

기초SELECT한빛유통311 / 700

상황 ​

고객센터 상담 화면의 고객 상세 아래쪽에는 「최근 주문 10건」 칸이 있고, 하루에 약 2만 번 열린다. 상담원 조민우가 캡처를 보내왔다. "어제 주문했다는 고객인데 이 칸에 어제 주문이 없어요. 날짜는 최신순으로 잘 줄 서 있는데 중간중간 비는 것 같아요." 화면 개발자의 답은 이랬다. "정렬은 ORDER BY ORD_DT DESC로 했고, 10건만 가져오려고 ROWNUM도 걸었다." 아래는 고객 CUS_000777을 열었을 때의 실행계획과 화면이다.

테이블과 인덱스 ​

  • T_ORD 주문: 100,000행 · 896블록 · PK_T_ORD (ORD_SEQ) · ORD_DT DATE(시분초 있음, 2023-01-01 ~ 2024-12-31) · 고객마다 약 50건 · 한 고객의 주문은 테이블 곳곳의 블록에 흩어져 있다
  • 고객 CUS_000777의 주문은 52건이고, 마지막 주문은 2024-12-30 19:42(어제)다
  • 인덱스 IX_T_ORD_CUS (CUS_ID): BLEVEL 1 · 리프 약 330블록 · 같은 CUS_ID 안에서는 ROWID 순서로 저장된다 · 통계 최신

원본 SQL ​

sql
SELECT ORD_SEQ, ORD_DT, ORD_ST, ORD_AMT
  FROM T_ORD
 WHERE CUS_ID = :cus
   AND ROWNUM <= 10
 ORDER BY ORD_DT DESC

실행계획 학습용 예시 ​

xplan
-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                             | Name         | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |              |      1 |        |     10 |00:00:00.01 |      12 |          |
|   1 |  SORT ORDER BY                        |              |      1 |     10 |     10 |00:00:00.01 |      12 | 2048  (0)|
|*  2 |   COUNT STOPKEY                       |              |      1 |        |     10 |00:00:00.01 |      12 |          |
|   3 |    TABLE ACCESS BY INDEX ROWID BATCHED| T_ORD        |      1 |     50 |     10 |00:00:00.01 |      12 |          |
|*  4 |     INDEX RANGE SCAN                  | IX_T_ORD_CUS |      1 |     50 |     10 |00:00:00.01 |       2 |          |
-----------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(ROWNUM<=10)
   4 - access("CUS_ID"=:CUS)

[화면 · CUS_000777 · 위에서부터]
  2024-11-02  2024-08-19  2024-07-30  2024-05-11  2024-03-08
  2023-12-27  2023-09-14  2023-06-02  2023-04-20  2023-01-15
  (실제 최근 주문 2024-12-30 · 2024-12-21 · 2024-12-09 … 는 화면에 없다)

문제 ​

  1. 화면의 10건이 '가장 최근 10건'이 아닌 까닭을 실행계획 1번 줄과 2번 줄의 위아래 관계로 설명하시오.
  2. 결과가 '가장 최근 주문 10건'이 되도록 SQL을 고치고, 10건만 읽고 멈추도록 인덱스도 제안하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자