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

점장 앱 달력에 「주문 있는 날」 점을 찍는 데 한 번에 1천 블록을 읽는다

실전SELECT버거349 / 700

상황 ​

점장 앱 첫 화면의 달력은 그 달에 주문이 있었던 날짜에 점을 찍는다. 200개 매장 점장이 앱을 열 때마다 호출되어 하루 약 6만 번 돌고, DBA가 뽑은 논리 읽기 순위에서 2위다. 개발팀이 세 가지 안을 냈다. ㉠ (SHOP_NO, ORD_DT) 인덱스를 새로 만든다. ㉡ 인덱스는 그대로 두고 그 달의 날짜(최대 31개)를 만들어 날마다 '그 매장 주문이 있는가'만 묻는다. ㉢ 매장별 일자별 주문 집계 테이블을 만들어 야간 배치로 채우고 달력은 그 테이블을 읽는다. 박팀장은 "숫자로 비교하고, 안마다 대가와 정합성 문제를 적어서 하나를 골라 달라. 주문 테이블 인덱스를 늘리려면 적재팀과 협의해야 한다는 것도 잊지 말고"라고 했다.

테이블과 인덱스 ​

  • ORD 주문: 1,000,000행 · 22,422블록 · SHOP_NO 200곳 · ORD_DT VARCHAR2(8) · 날짜순으로 쌓여 있다 · 하루 약 1,370건, 매장 하나는 하루 약 7건(하루 1 ~ 2건인 작은 매장도 있다) · 2013년 12월 42,408건
  • 인덱스 ORD_PK (ORD_NO), ORD_X01 (ORD_DT, ORD_HMS): BLEVEL 2 · 리프 약 3,500블록(한 블록에 약 286개) · CF 22,223
  • 아래 실행계획은 매장 SH0017(2013년 12월 주문 212건, 31일 모두 주문 있음)이다. 통계는 최신이다.

원본 SQL ​

sql
SELECT DISTINCT ORD_DT
  FROM ORD
 WHERE SHOP_NO = :shop
   AND ORD_DT BETWEEN :ym || '01' AND :ym || '31'
 ORDER BY ORD_DT

실행계획 학습용 예시 ​

xplan
[SH0017 · :ym = '201312']
--------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                            | Name    | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
--------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                     |         |      1 |        |     31 |00:00:00.03 |    1092 |       |       |          |
|   1 |  SORT UNIQUE                         |         |      1 |     31 |     31 |00:00:00.03 |    1092 |  2048 |  2048 | 2048  (0)|
|*  2 |   TABLE ACCESS BY INDEX ROWID BATCHED| ORD     |      1 |    211 |    212 |00:00:00.03 |    1092 |       |       |          |
|*  3 |    INDEX RANGE SCAN                  | ORD_X01 |      1 |  42466 |  42408 |00:00:00.01 |     150 |       |       |          |
--------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter("SHOP_NO"=:SHOP)
   3 - access("ORD_DT">=:YM||'01' AND "ORD_DT"<=:YM||'31')

문제 ​

  1. 점 31개를 찍는 데 1,092블록을 읽는 까닭을 실행계획 2번, 3번 줄의 A-Rows와 Predicate로 설명하시오.
  2. ㉠ ㉡ ㉢의 일량(평균 매장과 작은 매장), 대가, 정합성 문제를 비교하시오.
  3. 하나를 골라 SQL(필요하면 DDL)로 쓰고, 고른 까닭과 그 안을 바로 쓸 수 없을 때의 차선을 쓰시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자