programing

오라클 더 빠른 페이징 쿼리

telecom 2023. 9. 27. 16:55
반응형

오라클 더 빠른 페이징 쿼리

제가 사용할 것으로 생각하는 페이징 쿼리가 두 개 있습니다.

첫번째는.

SELECT * FROM ( SELECT rownum rnum, a.* from (
    select * from members
) a WHERE rownum <= #paging.endRow# ) where rnum > #paging.startRow#

그리고 두번째는

SELECT * FROM ( SELECT rownum rnum, a.* from (
    select * from members
) a ) WHERE rnum BETWEEN #paging.startRow# AND #paging.endRow#

어떤 쿼리가 더 빠른 쿼리라고 생각하십니까?

지금은 Oracle을 사용할 수 없지만 페이징에 가장 적합한 SQL 쿼리는 다음과 같습니다.

select *
from (
        select rownum as rn, a.*
        from (
                select *
                from my_table
                order by ....a_unique_criteria...
            ) a
    )
where rownum <= :size
    and rn >  (:page-1)*:size

http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html

일관된 페이징을 달성하려면 고유한 기준을 사용하여 행을 정렬해야 합니다. 이렇게 하면 페이지 Y(!=X)에 대해 이미 로드한 페이지 X 행을 로드하지 않습니다.

편집:

1) 고유한 기준을 사용하여 행을 정렬하는 것은 각 행이 쿼리를 실행할 때마다 동일한 위치를 유지하는 방식으로 데이터를 정렬하는 것을 의미합니다.

2) ORDER BY 절에 사용된 모든 표현이 포함된 인덱스를 사용하면 특히 첫 페이지에 대해 더 빠른 결과를 얻을 수 있습니다.이 인덱스를 사용하면 Optimizer가 선택한 실행 계획은 자연스러운 순서로 인덱스를 스크롤하는 행을 반환하므로 행을 정렬할 필요가 없습니다.

3) 그런데 질의 결과를 페이지화하는 가장 빠른 방법은 질의를 한 번만 실행하고 응용 프로그램 측의 모든 흐름을 처리하는 것입니다.

실행 계획을 살펴봅니다(예: 1000개 행).

SELECT *
  FROM (SELECT ROWNUM rnum
              ,a.*
          FROM (SELECT *
                  FROM members) a
         WHERE ROWNUM <= endrow#)
 WHERE rnum > startrow#;

--------------------------------------------------------------------------------
| Id  | Operation            | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |         |  1000 | 39000 |     3   (0)| 00:00:01 |
|*  1 |  VIEW                |         |  1000 | 39000 |     3   (0)| 00:00:01 |
|   2 |   COUNT              |         |       |       |            |          |
|*  3 |    FILTER            |         |       |       |            |          |
|   4 |     TABLE ACCESS FULL| MEMBERS |  1000 | 26000 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------

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

   1 - filter("RNUM">"STARTROW#")
   3 - filter("MEMBERS"."ENDROW#">=ROWNUM)

그리고 2개.

SELECT *
  FROM (SELECT ROWNUM rnum
              ,a.*
          FROM (SELECT *
                  FROM members) a)
 WHERE rnum BETWEEN startrow# AND endrow#;

-------------------------------------------------------------------------------
| Id  | Operation           | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |  1000 | 39000 |     3   (0)| 00:00:01 |
|*  1 |  VIEW               |         |  1000 | 39000 |     3   (0)| 00:00:01 |
|   2 |   COUNT             |         |       |       |            |          |
|   3 |    TABLE ACCESS FULL| MEMBERS |  1000 | 26000 |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------

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

   1 - filter("RNUM"<="ENDROW#" AND "RNUM">="STARTROW#")

그 중에서 버전 2는 한 단계가 덜 포함되어 있기 때문에 조금 더 빠를 수 있다고 생각합니다.하지만 귀사의 인덱스와 데이터 배포에 대해서는 잘 모르므로 이러한 실행 계획을 직접 수립하고 데이터에 대한 상황을 판단하는 것은 귀사에 달려 있습니다.아니면 그냥 시험해 보세요.

A씨는 이미 여기서 답변을 했습니다만, 복사해 드리겠습니다.

그냥 답과 댓글을 요약하고 싶어요.페이지를 작성하는 방법에는 여러 가지가 있습니다.

오라클 12c 이전에는 OFFSET/FETCH 기능이 없었으므로 @jasonk가 제안한 대로 백서를 살펴봅니다.장점과 단점에 대한 자세한 설명과 함께 다양한 방법에 대해 찾은 기사 중 가장 완성도가 높은 기사입니다.여기에 복사 붙여넣기를 하면 상당한 시간이 걸릴 것 같아요.

jooq 크리에이터들이 오라클과 다른 데이터베이스 페이지에 대한 몇 가지 일반적인 주의사항을 설명하는 좋은 기사도 있습니다.jooq의 블로그 포스트

좋은 소식입니다, 오라클 12c 이후로 새로운 OFFSET/FETCH 기능이 생겼습니다.오라클 매거진 12c 신기능"상위 N개 쿼리 및 페이지"를 참조하십시오.

아래 문을 발행하여 오라클 버전을 확인할 수 있습니다.

SELECT * FROM V$VERSION

언급URL : https://stackoverflow.com/questions/11680364/oracle-faster-paging-query

반응형