rhanziy

SQL - 페이징 기능 구현 쿼리 본문

Java

SQL - 페이징 기능 구현 쿼리

rhanziy 2023. 4. 27. 14:19

Database에 저장되어있는 페이지 개수만큼 페이지 목록을 출력하도록 구현된 경우,

1. 게시판 데이터가 많을수록 가독성이 떨어지고

2. 많은 데이터를 한 페이지에 불러오고 출력하는데 있어 시스템의 자원을 많이 사용한다.

는 문제점이 있다.

 

그래서 페이징 처리에 사용할 수 있는 쿼리의 종류에 대해 알아보자.

 

 

페이징 쿼리

1. Rownum을 통한 방식(Oracle, MariaDB)

2. LIMIT를 통한 방식(MySQL, MariaDB)

3. TOP을 통한 방식(MSSQL)

 

- Rownum

모든 SQL에 그대로 삽입해서 사용할 수 있는 가상의 컬럼(Column)이다. 해당 컬럼 값은 SQL이 실행되는 과정에서 발생하는 행의 일련번호를 뜻한다. 쉽게 말해 select를 통해 출력되는 결과 테이블에 행(Row)번호를 매겨주는 기능.

키워드와 함수 두가지 방식으로 사용이 가능하다.

 

 

Oracle Rownum 1방식

select rn, bno, title, content, writer, regdate, updatedate from(
 
        select /*+INDEX_DESC(vam_board pk_board) */ rownum as rn, bno, title, content, writer, regdate, updatedate
 
        from vam_board)
        -- select rownum as rownum as rn, bno, title, content, writer, regdate, updatedate from vam_board order by bno desc
 
where rn between 11 and 20;
    -- rn > 10 and rn <= 20;

 

 

 

서브쿼리만 실행했을 때,                                        where rn between 11 and 20; 까지 실행 했을 때 최종 결과

 

 

 

Oracle Rownum 2방식

select rn, bno, title, content, writer, regdate, updatedate from(
        select /*+INDEX_DESC(vam_board pk_board) */ rownum  as rn, bno, title, content, writer, regdate, updatedate 
        from vam_board where rownum <= 20) 
where rn > 10;

 

1방식 보다 실행속도가 빠르다. 이유는 반환하는 테이블의 크기 때문이다.

1방식의 경우 쿼리에서 테이블이 가지고있는 데이터를 모두 검색한 후 11-20사이의 결과값을 반환하지만

2방식의 경우 서브쿼리 검색조건에 의해 20개의 행만 검색 후 테이블을 반환하다.

정리하면 서브쿼리의 조건으로 인해 불필요한 검색을 하지 않음으로써 시간을 절약하여 검색속도를 향상시켰다.

Rownum의 뒷번호를 검색하는 경우에는 1방식과 2방식의 테이블의 크기가 거의 같기 때문에 검색속도가 비슷하다.

 


쿼리 결과를 보면 order by bno desc를 사용하지 않았음에도 최근에 저장된 행부터 출력된 것을 볼 수 있다. 

이러한 결과가 나오는 이유는 오라클 힌트(Hint)를 사용했기 때문이다.

 

 

힌트(Hint)란 개발자가 데이터베이스에 어떤 방식을 실행해줘야 하는지 명시하는 기능이다.

힌트가 왜 필요한지 실행계획(execution plan)에 대한 이해를 먼저 해보자.

 

오라클DB에서는 개발자가 작성한 쿼리를 실행할 때, SQL파싱 => SQL 최적화 => SQL 실행 단계를 거친다.

SQL파싱에서는 SQL구문에 오류가 있는지, SQL을 실행해야하는 대상 객체(테이블, 제약 조건, 권한 등)가 존재하는지를 체크한다.

SQL 최적화에서는 SQL이 실행되는데 필요한 비용(cost)를 계산한다.

SQL실행에서는 계산된 비용(cost)를 값을 기초로 하여 어떤 방식으로 실행하는 것이 좋은지를 판단한 실행계획을 세운다.

 

처리해야 할 데이터가 매우 많을 때에는 실행계획이 일관적으로 세워지지 않을수도 있다.

DBMS에서는 시스템과 DB의 상황을 고려하여 실행계획을 세우기 대문에 SQL문이 실행될 때 이전과 다른 실행계획을 가질 수도 있는 것이다. 문제는 최대한 빠른 결과를 내는 계획이 있음에도 다른 실행계획을 세울 수도 있다는 점이다.

이런 경우에 Hint를 사용하여 특정 실행 계획만을 사용하도록 지정해 줄 수 있다.

 

이러한 용도 외에도 매우 복잡한 구조의 테이블을 다루어야 하는 경우 개발자가 인위적으로 실행 순서를 조작하여 DB가 작성한 실행계획보다 더 나은 성능의 계획을 작성하기 위해서 Hint를 사용한다. 

 

order by bno desc가 아닌 인덱스 힌트(hint) 사용이유 -> 더 나은 성능의 실행계획이 잇음에도 정렬을 사용하는 다소 낮은 성능의 실행계획을 사용할 가능성을 없애기 위해!

어중간한 힌트로 인해 오히려 검색의 성능이 더 떨어질 수 있기에 힌트 사용에 확신을 할 수 없는 상황에서는 되도록이면 사용을 지양하자.

 

 

Oracle 실행계획 보는 법

 

MySQL 실행계획 보는 법


 

- LIMIT

select 문을 통해 데이터를 검색할 때, 검색 결과의 특정부분만 반환받고자 할 때 사용할 수 있는 기능이다.

검색하고자 하는 시작 행의 위치를 의미하는 데이터와 검색하고자 하는 행의 개수를 의미하는 데이터를 활용한다.

 

 

MySQL LIMIT

select bno, title, writer, regdate, updatedate  
from vam_board order by bno desc 
limit 10, 10;

위 코드의 limit는 limit <skip><count>를 의미한다. 10개의 행을 skip하고 10개의 행을 count한다는 의미.

만약 51행부터 60행을 원한다면 limit 50, 10을 작성하면 된다.

limit방식은 rownum방식에 비해 전체적으로 빠른 검색속도를 보여준다. 하지만 limit도 뒷행으로 갈수록 검색 속도가 느려지는 현상은 동일하다.

 

 

Comments