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

지역장 화면의 「담당 매장 최근 주문 20건」, 담당 매장이 많은 지역장일수록 무겁다

실전SELECT버거321 / 700

상황 ​

지역장 12명은 담당 매장(3 ~ 40곳)의 최근 주문 20건을 한 화면에서 보고, 화면은 30초마다 새로 고친다. 40곳을 맡은 지역장 SV07의 화면은 3곳을 맡은 SV02의 화면보다 열 배 넘게 무겁다. 개발팀은 세 가지 안을 냈다. ㉠ 지금 SQL은 그대로 두고 인덱스를 더 만든다. ㉡ 시각순 인덱스 ORD_X01을 거꾸로 읽으며 담당 매장만 거른다. ㉢ 매장마다 최근 20건을 따로 뽑아 합친다. 박팀장은 "세 안을 숫자로 비교해서 하나를 골라 달라. 지역장마다 매장 수가 다르다는 것도 잊지 말고"라고 했다.

테이블과 인덱스 ​

  • ORD 주문: 1,000,000행 · 22,422블록 · 날짜순 적재(CF 좋음) · 매장 200곳, 매장마다 약 5,000건 · ORD_DT, ORD_HMS NOT NULL
  • SV_SHOP 지역장 담당 매장(이 문제에서 쓰는 파생 테이블): SV_ID · SHOP_NO · 200행 · 5블록 · PK SV_SHOP_PK (SV_ID, SHOP_NO) · 지역장 12명, 담당 매장 3 ~ 40곳
  • 인덱스 ORD_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 약 3,500블록 · ORD_X02 (SHOP_NO, ORD_DT, ORD_HMS, ORD_NO): BLEVEL 2 · 리프 약 5,200블록(매장 하나에 약 26블록) · 통계 최신
  • 화면 칸은 ORD_NO, SHOP_NO, ORD_DT, ORD_HMS 넷이고 모두 ORD_X02에 있다

원본 SQL ​

sql
SELECT o.ORD_NO, o.SHOP_NO, o.ORD_DT, o.ORD_HMS
  FROM ORD o
 WHERE o.SHOP_NO IN (SELECT v.SHOP_NO FROM SV_SHOP v WHERE v.SV_ID = :sv)
 ORDER BY o.ORD_DT DESC, o.ORD_HMS DESC, o.ORD_NO DESC
 FETCH FIRST 20 ROWS ONLY

실행계획 학습용 예시 ​

xplan
[SV07 · 담당 매장 40곳]
---------------------------------------------------------------------------------------------------------------
| Id  | Operation                | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Used-Mem |
---------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT         |            |      1 |        |     20 |00:00:00.11 |    1122 |          |
|*  1 |  VIEW                    |            |      1 |     20 |     20 |00:00:00.11 |    1122 |          |
|*  2 |   WINDOW SORT PUSHED RANK|            |      1 |  85000 |     20 |00:00:00.11 |    1122 | 6144  (0)|
|   3 |    NESTED LOOPS          |            |      1 |  85000 |    200K|00:00:00.07 |    1122 |          |
|*  4 |     INDEX RANGE SCAN     | SV_SHOP_PK |      1 |     17 |     40 |00:00:00.01 |       2 |          |
|*  5 |     INDEX RANGE SCAN     | ORD_X02    |     40 |   5000 |    200K|00:00:00.05 |    1120 |          |
---------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("from$_subquery$_003"."rowlimit_$$_rownumber"<=20)
   2 - filter(ROW_NUMBER() OVER ( ORDER BY INTERNAL_FUNCTION("O"."ORD_DT") DESC ,INTERNAL_FUNCTION("O"."ORD_HMS") DESC ,INTERNAL_FUNCTION("O"."ORD_NO") DESC )<=20)
   4 - access("V"."SV_ID"=:SV)
   5 - access("O"."SHOP_NO"="V"."SHOP_NO")

[SV02 · 담당 매장 3곳]  같은 모양 · 5번 줄 Starts 3 · A-Rows 15K · Buffers 86

문제 ​

  1. 매장마다 주문이 (일자, 시각, 주문번호) 순서로 줄 선 ORD_X02가 있는데도 2번 줄에서 정렬이 일어나는 까닭과, 지역장의 매장 수에 따라 일량이 어떻게 늘어나는지 설명하시오.
  2. ㉡안과 ㉢안이 SV07(40곳)과 SV02(3곳)에서 각각 몇 블록쯤 읽는지 어림하고, 어느 경우에 어느 안이 불리해지는지 쓰시오.
  3. 한 안을 골라 SQL로 쓰고, 그 안의 부작용과 정렬 키 끝에 주문번호를 둔 까닭을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자