sort order by 페이지 별 성능 문제 최적화

개발 자 는 백 스테이지 에서 특정한 업무 데이터 내 역 을 조회 하 는 것 이 매우 느 려 서 최적화 하 라 고 말 했다.
그리고 저 는 회사 플랫폼 에 가서 페이지 의 조 회 를 클릭 한 결과 6 분 이 걸 렸 습 니 다. 그리고 sql 을 잡 아 냈 는데 5 개의 표 와 관련 된 페이지 문 구 였 습 니 다.
그 중에서 4 개의 시 계 는 몇 M 밖 에 안 되 고 큰 시 계 는 15G 이 며 작은 시 계 는 고려 할 필요 가 없다. 그리고 나 는 큰 시 계 를 꺼 내 서 단독으로 페이지 를 나 누 어 조회 한 결과 똑 같이 6 분 이 걸 렸 다. 문장 과 집행 계획 은 다음 과 같다.
SQL> explain plan for 
  2  SELECT *
  FROM (SELECT t.*, rownum AS rn
          FROM  (SELECT *
                   FROM tb_recharge
                  WHERE create_date >= to_date('2014-09-01 00:00:00','yyyy-mm-dd hh24:mi:ss')
                    AND create_date < to_date('2014-10-01 00:00:00','yyyy-mm-dd hh24:mi:ss')
                  ORDER BY id desc) t
         WHERE rownum <= 10
         )
 11   WHERE rn > 0
 12  /

Explained.


Elapsed: 00:00:00.15

SQL> set lines 200 pages 200;
SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 4050647635

-------------------------------------------------------------------------------------------------------------------------
| Id  | Operation          | Name| Rows| Bytes | Cost (%CPU)| Time| Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               ||     1 |  2047 |     1 (100)| 00:00:01 |||
|*  1 |  VIEW                   ||     1 |  2047 |     1 (100)| 00:00:01 |||
|*  2 |   COUNT STOPKEY                ||||     ||||
|   3 |    VIEW                    ||     1 |  2034 |     1 (100)| 00:00:01 |||
|*  4 |     SORT ORDER BY STOPKEY           ||     1 |  2034 |     1 (100)| 00:00:01 |||
|   5 |      PARTITION RANGE SINGLE           ||     1 |  2034 |     0   (0)| 00:00:01 |    14 |    14 |
|   6 |       TABLE ACCESS BY LOCAL INDEX ROWID| TB_RECHARGE|     1 |  2034 |     0   (0)| 00:00:01 |    14 |    14 |
|*  7 |        INDEX RANGE SCAN            | TB_RECHARGE_I5 |     1 ||     0   (0)| 00:00:01 |    14 |    14 |
-------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN">0)
   2 - filter(ROWNUM<=10)
   4 - filter(ROWNUM<=10)
   7 - access("CREATE_DATE">=TO_DATE(' 2014-09-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
     "CREATE_DATE"<TO_DATE(' 2014-10-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

23 rows selected.

Elapsed: 00:00:05.38

이 문 구 는 orderby 를 제거 하고 매우 빠 른 ms 단 계 를 발견 하여 데 이 터 를 되 돌려 줍 니 다. 그러면 orderby 가 성능 문 제 를 일 으 켰 다 고 단정 할 수 있 습 니 다. 그리고 저 는 count 를 통 해 데이터 600 여 만 줄 을 발 견 했 습 니 다.
sql 에 서 는 createdate 필터, id 정렬, 그래서 CBO 는 필터 후의 데이터 id 가 질서 가 있 는 지 판단 할 수 없습니다.
그래서 실행 계획 4 에 SORT ORDER BY STOPKEY 가 나 왔 습 니 다. first 를 가지 않 았 습 니 다.rows 특성 상 600 여 만 줄 에 order by 를 진행 하 였 기 때문에 속도 가 느 립 니 다.
create 에 따 르 면date 정렬 하면 fistrows, 그리고 개발 자 에 게 시간 필드 에 따라 정렬 할 수 있 는 지 물 었 습 니 다. 개발 자 는 안 된다 고 했 습 니 다. 같은 시간 에 데이터 가 많 기 때문에 정렬 이 혼 란 스 러 울 수 있 습 니 다. 그러면 다른 방법 을 사용 할 수 밖 에 없습니다.
다음은 나의 해결 방식 이다.
createdate, id 조합 index, orderby id 를 ORDER BY 로 변경 create_date DESC, id DESC 가 index 를 만 들 고 고 친 sql 은 다음 과 같 습 니 다.
SQL> explain plan for 
  2  SELECT *
  FROM (SELECT t.*, rownum AS rn
          FROM  (SELECT /*+ index_desc(tb_recharge IDX_CREATEDATE_ID)*/*
                   FROM tb_recharge
                  WHERE create_date >= to_date('2014-09-01 00:00:00','yyyy-mm-dd hh24:mi:ss')
                    AND create_date < to_date('2014-10-01 00:00:00','yyyy-mm-dd hh24:mi:ss')
                  ORDER BY  create_date DESC, id DESC ) t
         WHERE rownum <= 10
         )
 11   WHERE rn > 0
 12  /

SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 3687185489

---------------------------------------------------------------------------------------------------------------------------
| Id  | Operation      | Name  | Rows  | Bytes | Cost (%CPU)| Time  | Pstart| Pstop |
---------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |   |1 |  2047 |3  (67)| 00:00:01 |  |  |
|*  1 |  VIEW      |   |1 |  2047 |3  (67)| 00:00:01 |  |  |
|*  2 |   COUNT STOPKEY       |   |  |  |       |  |  |  |
|   3 |    VIEW       |   |1 |  2034 |3  (67)| 00:00:01 |  |  |
|   4 |     PARTITION RANGE SINGLE      |   |1 |  2034 |3  (67)| 00:00:01 |    14 |    14 |
|   5 |      TABLE ACCESS BY LOCAL INDEX ROWID| TB_RECHARGE  |1 |  2034 |3  (67)| 00:00:01 |    14 |    14 |
|*  6 |       INDEX RANGE SCAN DESCENDING     | IDX_CREATEDATE_ID |1 |  |    71   (0)| 00:00:01 |    14 |    14 |
---------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN">0)
   2 - filter(ROWNUM<=10)
   6 - access("CREATE_DATE">=TO_DATE(' 2014-09-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "CREATE_DATE"<TO_DATE('
     2014-10-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'))

21 rows selected.

Elapsed: 00:00:00.07

최적화 후 ms 단 계 를 되 돌려 줍 니 다. 실행 계획 중 SORT ORDER BY STOPKEY 가 사 라 졌 습 니 다. 6 단계 에서 INDEX RANGE SCAN DESCENDING 을 걸 었 습 니 다. 고급 실행 계획 을 사용 하면 cbo 가 10 줄 만 방문 한 것 을 볼 수 있 습 니 다.
stop 에서 데 이 터 를 되 돌려 줍 니 다.
본 고 는 'Oracle 성능 개선 에 전념 하 라' 블 로그 에서 나 온 것 으로 전 재 를 사절 합 니 다!

좋은 웹페이지 즐겨찾기