목록 페이지에서 페이징 처리하기
페이징 처리 방법
번호를 이용한 페이징 처리하기
데이터 양이 많을수록 정렬을 위한 리소스 소모 ↑
따라서 빠른 SQL 동작을 위해서는 order by 사용 가능한 ❌
SQL 파싱
SQL 구문에 오류 존재하는지, SQL 실행 대상 객체 (테이블, 제약 조건 등) 존재하는지 검사
SQL 최적화
SQL 실행에 필요한 비용 계산
계산 값 기반으로 어떤방식으로 실행하는 것이 가장 적절한지 실행계획 세움
SQL 실행
실행계획은 DB에서 생성하고 매번 달라진다. 보통 정렬하느라 시간 소모가 제일 많이 된다.
데이터양이 많을 때 정렬 작업이 문제가 되는 것을 해결하기 위해 일반적으로 인덱스를 사용한다.
인덱스는 이미 정렬된 구조이기 때문에 이를 이용하면 별도의 정렬이 필요하지 않다.
테이블 생성 시 지정한 PK가 구조상 인덱스 객체를 생성한다.
테이블은 보통 정렬이 안되어 있어서 이미 정렬된 인덱스를 이용하여 찾게된다.
ROWID는 DB 내의 데이터의 고유 주소이며 이를 이용하여 인덱스와 실제 테이블 데이터를 연결한다.
인덱스는 이미 정렬이 되어있으니까 데이터를 찾아서 해당 데이터들을 SORT 하는 과정 생략 가능
(그냥 정렬하면 select 시 테이블 전체를 scan 해준 후 정렬해야 하니까 시간이 오래 걸림)
예를 들어, bno 역순으로 정렬한 결과를 얻기 위해서는 이미 정렬된 인덱스를 뒤에서부터 찾으면 됨 (desc)
인덱스를 역순으로 찾기에 가장 먼저 찾은 bno는 가장 큰 값을 가진 데이터일것이고 이를 반복하면 자동으로 정렬된 결과가 나타난다.
보통 웹페이지에서는 시간의 역순으로 정렬된 결과를 (최신순으로) 보여준다.
오라클은 select문 전달 시 hint를 사용가능. (힌트는 select문을 어떻게 처리할것인지에 대한 설명이어서 힌트에서 오류나도 SQL 실행에는 지장이 없다.)
일반적인 방식
SELECT * FROM TBL_BOARD ORDER BY DESC;
DB 상황에 따라 테이블의 모든 데이터를 정렬해야할 수도 있다.
반면 힌트를 사용하면 DB에게 SQL 실행 방식을 명시해주기 때문에 강제성을 부여할 수 있다.
SELECT /*+INDEX_DESC (tbl_board pk_board) */*
FROM TBL_BOARD;
SELECT
/*+ [HINT name] (param...) */ [column name], ...
FROM [table name]
SELECT /*+ FULL(tbl_board)*/ * FROM tbl_board ORDER BY bno DECS;
ORDER BY
사용을 위해 쓴다.ROWNUM : SQL이 실행한 결과에 넘버링해준다.
실제 값이 아닌 테이블에서 데이터를 추출한 후 처리되는 변수임으로 상황따라 값이 변한다.
SELECT rownum rn, bno, title FROM tbl_board;
만약 힌트를 이용하여 정렬된 데이터를 꺼낸다면 아래와 같은 순서로 처리된다.
즉 정렬되는 과정에서는 rownum이 변하지 않는다.
ROWNUM은 테이블에서 데이터를 가져오면서 붙는 번호 → 테이블에 어떤 순서로 접근하느냐에 따라 ROWNUM값이 달라진다는 의미.
SELECT
/*+ INDEX_DESC(tbl_board pk_board)*/
rownum rn, bno, title, content
FROM tbl_board
where bno > 0;
WHERE
절에 rownum 관련 조건을 줄 수 있다.
SELECT
/*+ INDEX_DESC(tbl_board pk_board)*/
rownum rn, bno, title, content
FROM tbl_board
where rownum <= 10;
위의 코드를 실행하면 10개만 출력되고 실행계획을 확인해보면 아래와 같다
ROWNUM이 필터링 조건으로 적용되었음.
SELECT
/*+ INDEX_DESC(tbl_board pk_board)*/
rownum rn, bno, title, content
FROM tbl_board
where rownum <= 20 AND rownum > 10;
이렇게하면 아무런 결과가 안나옴
왜임?!!
실행계획을 한번 보겟음
실행계획은 안 → 밖, 위 → 아래 순서로
ROWNUM > 10 데이터 추출
이 때 tbl_board의 첫 rownum은 1이 됨
rownum이 1이기 때문에 where절에 의해 조건이 무효화됨
다시 새로운 데이터를 가져오면 새로운 데이터가 첫번째 데이터가 된다. 즉 다시 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;
위 코드를 수행하면 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;
- 필요한 순서로 정렬된 데이터에 ROWNUM 배정
- 처음 ~ 끝 까지의 데이터를 'rownum <= 30'과 같은 조건을 이용하여 추출
- 중첩 SELECT문 활용