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

매장 판매 일지에서 세 쪽 넘게 넘긴 뒤 「이전」을 누르면 늘 첫 쪽이 나온다

중급SELECT유통336 / 700

상황 ​

본사 영업지원팀의 「매장 판매 일지」는 매장 하나의 판매를 최근 것부터 한 쪽에 50건씩 보여 주고, 「다음」과 「이전」 버튼으로 넘긴다. 화면은 지금 쪽의 첫 판매번호와 마지막 판매번호를 들고 있다가 「다음」에는 마지막 번호를, 「이전」에는 첫 번호를 넘긴다. 팀원들은 "「다음」은 잘 넘어가는데 5쪽에서 「이전」을 누르면 4쪽이 아니라 1쪽이 나온다. 2쪽에서 누를 때만 맞다"라고 한다. 판매번호는 유일해서 쪽 경계에서 판매가 빠지거나 겹친 일은 없었다.

테이블과 인덱스 ​

  • CF10 판매: 500,000행 · 4,583블록 · SLE_NO VARCHAR2(15) '20231231-0612'(판매일 + 그날 일련번호, 판매 순서대로 매긴다, 유일) · SHP_NO(판매가 있는 매장 5곳, 매장마다 약 10만 건) · SLE_DT · SLE_HMS
  • 인덱스 CF10_PK (SLE_NO), CF10_X02 (SHP_NO, SLE_NO)(이 화면용) · CF10_X02는 BLEVEL 2 · 리프 약 1,900블록
  • 판매는 판매번호 순서로 쌓여 있어 매장 하나의 이어진 50건은 테이블 블록 서너 개에 모여 있다. 통계는 최신이다.

원본 SQL ​

sql
-- 다음 : 지금 쪽 마지막 판매번호(:last_no)보다 앞선 50건
SELECT SLE_NO, SLE_DT, SLE_HMS
  FROM (SELECT SLE_NO, SLE_DT, SLE_HMS
          FROM CF10
         WHERE SHP_NO = :shp
           AND SLE_NO < :last_no
         ORDER BY SLE_NO DESC)
 WHERE ROWNUM <= 50;

-- 이전 : 지금 쪽 첫 판매번호(:first_no)보다 뒤인 50건
SELECT SLE_NO, SLE_DT, SLE_HMS
  FROM (SELECT SLE_NO, SLE_DT, SLE_HMS
          FROM CF10
         WHERE SHP_NO = :shp
           AND SLE_NO > :first_no
         ORDER BY SLE_NO DESC)
 WHERE ROWNUM <= 50;

실행계획 학습용 예시 ​

xplan
[이전 · 5쪽에서 누름 · :shp = '1003', :first_no = '20231230-0349']
------------------------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |      1 |        |     50 |00:00:00.01 |       7 |
|*  1 |  COUNT STOPKEY                  |          |      1 |        |     50 |00:00:00.01 |       7 |
|   2 |   VIEW                          |          |      1 |     50 |     50 |00:00:00.01 |       7 |
|   3 |    TABLE ACCESS BY INDEX ROWID  | CF10     |      1 |   5000 |     50 |00:00:00.01 |       7 |
|*  4 |     INDEX RANGE SCAN DESCENDING | CF10_X02 |      1 |     50 |     50 |00:00:00.01 |       3 |
------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(ROWNUM<=50)
   4 - access("SHP_NO"=:SHP AND "SLE_NO">:FIRST_NO)

[화면 · 1003 매장]
  1쪽   20231231-0684 ~ 20231231-0431
  4쪽   20231230-0604 ~ 20231230-0355
  5쪽   20231230-0349 ~ 20231230-0101   ← 여기서 「이전」
  결과  20231231-0684 ~ 20231231-0431   (1쪽과 같다)

문제 ​

  1. 2쪽에서는 맞던 「이전」이 3쪽부터 늘 1쪽을 보여 주는 까닭을 실행계획 4번 줄의 조건과 읽는 방향으로 설명하시오.
  2. 화면 순서(최근 것부터)는 그대로 두고 「이전」이 바로 앞 쪽 50건을 보여 주도록 SQL을 고치시오.
  3. 고친 SQL에서 ROWNUM과 두 ORDER BY를 각각 어디에 두어야 하는지 그 까닭과 함께 설명하시오.
원본 SQL을 고쳐 쓰세요. 인덱스 DDL과 힌트도 쓸 수 있습니다.
무엇이 문제였고 왜 이렇게 고쳤는지 쓰세요.0자