1.order by 문제:
데이터베이스에서 가장 신경쓰는 부분은 빠르게 처리되는 것, 필요한 양만큼만 데이터를 가져오는 것.
빠르게 동작하는 sql을 위해서는 order by를 이용하는 작업을 가능하면 사용하지 말아야한다.
엄청난 성능 저하를 가져오기 때문에
데이터가 적을 경우와 정렬을 빠르게 할 수 있는 방법이 있는 경우가 아니라면 order by는 주의해야만 한다.
2. 실행 계획과 order by
실행 계획: sql을 데이터베이스에서 어떻게 처리할 것인가?
SQL파싱: 구문에 오류가 있는지, 실행해야하는 대상이 존재하는지
SQL 최적화: 실행되는데 필요한 비용을 계산, 어떤 방식으로 실행하는 것이 가장 좋다는 것을 판단하는 실행계획을 세움
SQL 실행: 메모리상에 데이터를 읽거나 물리적인 공간에서 데이터를 로딩하는 등의 작업
2.1 order by 보다 인덱스
인덱스라는 존재가 이미 정렬된 구조이므로 이를 이용해서 별도의 정렬을 하지 않는다.
select /*+ INDEX_DESC(spring_board sparing_board_pk) */
*
from spring_board where b_num >0;
1)sort를 하지 않는다.
2)spring_board를 바로 접근하는 것이 아니라 spring_board_pk를 이용해서 접근
제약조건명이 인덱스명
3.인덱스와 오라클 힌트
오라클은 select문을 전달할 때 힌트라는 것을 사용할 수 있다. 힌트는 개발자가 데이터베이스에 어떤 방식으로 실행해줘야하는지를 명시하기 때문에 조금 강제성이 부여되는 방식이다.
select문을 작성할 때 힌트는 잘못 작성되어도 실행할 때는 무시되기만하고 별도의 에러는 발생하지 않는다.
/*+로 시작하고 */로 끝난다.
FULL(테이블명): /*+FULL(spring_board)*/
INDEX_ASC, INDEX_DESC: /*+INDEX_DESC(spring_board spring_board_pk)*/
DESC(테이블명 인텍스명)
인덱스명: 기본키=> spring_board_pk
4.rownum과 인라인 뷰
전체가 아닌 필요한 만큼의 데이터를 가져오는 방식. 오라클 데이터베이스는 페이지 처리를 위해서 rownum이라는 키워드를 사용해서 데이터에 순번을 붙여 사용.
select rownum, b_num, b_name, b_title, to_char(b_data, 'YYYY-MM-DD') as b_date
from spring_board;
1번 부터 10번까지
select /*+INDEX_DESC(spring_board spring_board_pk)*/ rownum, b_num, b_name, b_title, to_char(b_data, 'YYYY-MM-DD') as b_date
from spring_board where rownum <=10;
2페이지 데이터를 구하기 위해 11번 부터 20번까지의 데이터 출력
select /*+INDEX_DESC(spring_board spring_board_pk)*/ rownum, b_num, b_name, b_title, to_char(b_data, 'YYYY-MM-DD') as b_date
from spring_board where rownum <=20 and rownum >10;
결과는 아무 데이터도 출력하지 않는다. rownum 조건은 반드시 1이 포함되어야한다.
select /*+INDEX_DESC(spring_board spring_board_pk)*/ rownum, b_num, b_name, b_title, to_char(b_data, 'YYYY-MM-DD') as b_date
from spring_board where rownum <=20; --반드시 1이 포함되도록 해야한다.
인라인 뷰 처리(rownum의 별칭 rnum)
SELECT
rnum, b_num, b_name, b_title, to_char(b_data, 'YYYY-MM-DD') as b_date
from( //안쪽에는 함수 쓰면 안됨.
select /*+INDEX_DESC(spring_board spring_board_pk)*/
rownum asrnum, b_num, b_name, b_title, b_date
from spring_board
where rownum <=20
) boardlist
where rnum >10;
--순서정리
필요한 순서로 정렬된 데이터에 rownum을 붙인다.
처음부터 해당 페이지의 데이터를 rownum <=20과 같은 조건을 이용해서 구한다.
구해놓은 데이터를 하나의 테이블처럼 간주하고 인라인뷰로 처리한다.
인라인뷰에서 필요한 데이터만을 남긴다.
페이징 처리
페이징 처리를 위해서 필요한 파라미터: 페이지 번호, 한 페이지당 몇 개의 데이터를 보여줄 것인지가 결정되어야 한다.
pageNum*amount
(pageNum-1)*amount
화면에 페이징처리
화면 페이지는 다음과 같은 정보들이 필요
현재 페이지 번호, 이전과 다음으로 이동 가능한 링크의 표시 여부, 화면에서 보여지는 페이지의 시작번호와 끝번호
5페이지를 본다면 1페이지 부터 10페이지 안에서의 5페이지, 15페이지를 본다면 11페이지 부터 시작
페이징의 끝번호(endPage) 계산
this.endPage = (int)(Math.ceil(cvo.getPageNum()/10.0))*10;
-1페이지: Math.ceil(0.1)*10 = 10
-2페이지: Math.ceil(0.2)*10 = 10
-10페이지: Math.ceil(1)*10 = 10
-11페이지: Math.ceil(1.1)*10 = 20
-20페이지: Math.ceil(2)*10 = 20
페이징의 시작번호 계산
this.startPage = this.endPage-9;
끝번호(endPage)는 전체 데이터수에 의해서 영향을 받는다.
int realEnd = (int) (Math,ceil(total*1.0)/cvo.getAmount()));
if(realEnd <= this.endPage){
this.endPage = realEnd;
}