오라클 DB 페이징 처리

김주언·2022년 9월 8일
0

Spring

목록 보기
8/15
post-thumbnail

목록 페이지에서 페이징 처리하기

페이징 처리 방법

  1. 번호 이용
  2. 계속 보기 형식 → Ajax를 이용한 무한 스크롤 또는 더보기 형태

번호를 이용한 페이징 처리하기


1.오라클 DB에서 페이징 처리를 위한 개념

1.1 order by

데이터 양이 많을수록 정렬을 위한 리소스 소모 ↑
따라서 빠른 SQL 동작을 위해서는 order by 사용 가능한 ❌

실행계획 execution plan

SQL 처리 과정

  1. SQL 파싱
    SQL 구문에 오류 존재하는지, SQL 실행 대상 객체 (테이블, 제약 조건 등) 존재하는지 검사

  2. SQL 최적화
    SQL 실행에 필요한 비용 계산
    계산 값 기반으로 어떤방식으로 실행하는 것이 가장 적절한지 실행계획 세움

  3. SQL 실행

실행계획은 DB에서 생성하고 매번 달라진다. 보통 정렬하느라 시간 소모가 제일 많이 된다.



1.2 인덱스

데이터양이 많을 때 정렬 작업이 문제가 되는 것을 해결하기 위해 일반적으로 인덱스를 사용한다.

인덱스는 이미 정렬된 구조이기 때문에 이를 이용하면 별도의 정렬이 필요하지 않다.
테이블 생성 시 지정한 PK가 구조상 인덱스 객체를 생성한다.

테이블은 보통 정렬이 안되어 있어서 이미 정렬된 인덱스를 이용하여 찾게된다.
ROWID는 DB 내의 데이터의 고유 주소이며 이를 이용하여 인덱스와 실제 테이블 데이터를 연결한다.



1.3 인덱스 활용 정렬

인덱스는 이미 정렬이 되어있으니까 데이터를 찾아서 해당 데이터들을 SORT 하는 과정 생략 가능
(그냥 정렬하면 select 시 테이블 전체를 scan 해준 후 정렬해야 하니까 시간이 오래 걸림)

예를 들어, bno 역순으로 정렬한 결과를 얻기 위해서는 이미 정렬된 인덱스를 뒤에서부터 찾으면 됨 (desc)

인덱스를 역순으로 찾기에 가장 먼저 찾은 bno는 가장 큰 값을 가진 데이터일것이고 이를 반복하면 자동으로 정렬된 결과가 나타난다.


1.3.1 인덱스와 오라클 힌트

보통 웹페이지에서는 시간의 역순으로 정렬된 결과를 (최신순으로) 보여준다.

오라클은 select문 전달 시 hint를 사용가능. (힌트는 select문을 어떻게 처리할것인지에 대한 설명이어서 힌트에서 오류나도 SQL 실행에는 지장이 없다.)

일반적인 방식

SELECT * FROM TBL_BOARD ORDER BY DESC;

DB 상황에 따라 테이블의 모든 데이터를 정렬해야할 수도 있다.

반면 힌트를 사용하면 DB에게 SQL 실행 방식을 명시해주기 때문에 강제성을 부여할 수 있다.

SELECT /*+INDEX_DESC (tbl_board pk_board) */* 
FROM TBL_BOARD;

1.3.2 힌트 사용 문법

SELECT
/*+ [HINT name] (param...) */ [column name], ...
FROM [table name]

  • FULL 힌트
    select문 실행 시 테이블 전체를 스캔하도록 한다.
SELECT /*+ FULL(tbl_board)*/ * FROM tbl_board ORDER BY bno DECS;
  • INDEX_ASC / INDEX_DESC 힌트
    인덱스를 순서대로, 역순으로 이용
    주로 ORDER BY 사용을 위해 쓴다.


1.4 ROWNUM과 인라인뷰

ROWNUM : SQL이 실행한 결과에 넘버링해준다.
실제 값이 아닌 테이블에서 데이터를 추출한 후 처리되는 변수임으로 상황따라 값이 변한다.

SELECT rownum rn, bno, title FROM tbl_board;

만약 힌트를 이용하여 정렬된 데이터를 꺼낸다면 아래와 같은 순서로 처리된다.

  1. SELECT 결과 추출
  2. ROWNUM 배정
  3. 정렬

즉 정렬되는 과정에서는 rownum이 변하지 않는다.

1.4.1 인덱스를 이용한 접근과 ROWNUM

ROWNUM은 테이블에서 데이터를 가져오면서 붙는 번호 → 테이블에 어떤 순서로 접근하느냐에 따라 ROWNUM값이 달라진다는 의미.

PK_BOARD 인덱스를 통한 접근 시

  1. 인덱스를 통해 테이블에 접근
    → 이미 정렬이 된 상태
  2. 접근한 데이터에 ROWNUM 부여
SELECT
/*+ INDEX_DESC(tbl_board pk_board)*/
rownum rn, bno, title, content
FROM tbl_board
where bno > 0;




2. 페이징 처리

2.1 1페이지

WHERE절에 rownum 관련 조건을 줄 수 있다.

SELECT
/*+ INDEX_DESC(tbl_board pk_board)*/
rownum rn, bno, title, content
FROM tbl_board
where rownum <= 10;

위의 코드를 실행하면 10개만 출력되고 실행계획을 확인해보면 아래와 같다

ROWNUM이 필터링 조건으로 적용되었음.

2.2 2페이지

SELECT
/*+ INDEX_DESC(tbl_board pk_board)*/
rownum rn, bno, title, content
FROM tbl_board
where rownum <= 20 AND rownum > 10;

이렇게하면 아무런 결과가 안나옴

왜임?!!

실행계획을 한번 보겟음

실행계획은 안 → 밖, 위 → 아래 순서로

  1. ROWNUM > 10 데이터 추출
    이 때 tbl_board의 첫 rownum은 1이 됨

  2. rownum이 1이기 때문에 where절에 의해 조건이 무효화됨

  3. 다시 새로운 데이터를 가져오면 새로운 데이터가 첫번째 데이터가 된다. 즉 다시 rownum이 1이 된다.

위 과정을 반복하며 rownum은 항상 1이 됨. 즉 모든 데이터를 찾아내지만 결과는 아무것도 나오지 않는 것

💡 따라서 이러한 SQL 작성 시 rownum은 반드시 1이 포함 되어야 한다.

SELECT
/*+ INDEX_DESC(tbl_board pk_board)*/
rownum rn, bno, title, content
FROM tbl_board
where rownum <= 20;

2.2.1 인라인 뷰 처리

위 코드를 수행하면 1페이지의 내용까지 함께 출력된다 → 중첩 SELECT 활용

인라인 뷰는 뷰를 별도로 작성하지 않고 FROM 구문 앞에 바로 작성하는 형태

SELECT bno, title, content 
FROM (SELECT
      /*+ INDEX_DESC(tbl_board pk_board)*/
      rownum rn, bno, title, content
      FROM tbl_board
      where rownum <= 20
      )
WHERE rn > 10;

  1. 필요한 순서로 정렬된 데이터에 ROWNUM 배정
  2. 처음 ~ 끝 까지의 데이터를 'rownum <= 30'과 같은 조건을 이용하여 추출
  3. 중첩 SELECT문 활용
profile
학생 점심을 좀 차리시길 바랍니다

0개의 댓글