일반 5백만건의 데이터량을 페이징

황제낙엽 2007.06.08 04:05 조회 수 : 252 추천:74

sitelink1  
sitelink2  
extra_vars5
extra_vars6 ko 

지금 5백만건 정도 되는 1개의 테이블의 데이터를 10개 단위로 페이징해서

보여주려고 하는데
앞부분의 페이지는 보여주는 속도가 빠른데
뒷부분으로 갈수록 느려지더군요.
아무리 인덱스를 사용하고 머리를 굴려도
뒷부분으로 갈수록 속도가 느려지는건 해결할수가 없더라구요.
테이블을 나누지 않고 이 테이블 그대로에서
페이징속도를 앞부분이나 뒷부분이나 구분없이
일정하게 똑같이 빠르게 할수 있는 방법이 있는지요.

 

create table FILE_UPLOAD
(
SEQ_NO NUMBER(9) not null,
DIR_NAME VARCHAR2(50) not null,
FILE_NAME VARCHAR2(100) not null,
FST_REG_ID VARCHAR2(10),
FST_REG_DT DATE,
FST_REG_DT_SORT VARCHAR2(18) not null
)

 

이렇게 테이블을 생성하고 pk는 a로 잡았고
FST_REG_DT_SORT 에만 인덱스를 따로 잡았습니다.

 

select rnum, seq_no, dir_name, file_name, fst_reg_id, fst_reg_dt, fst_reg_dt_sort
from( select /*+ index_asc(file_upload, FILE_UPLOAD_SEQ_NO_PK) */
seq_no, rownum as rnum, dir_name, file_name, fst_reg_id, fst_reg_dt, fst_reg_dt_sort
from file_upload where seq_no > 0 )
where rnum >= ( (선택한 페이지 - 1) * 페이지당보여질갯수 + 1) and rownum <= 페이지당보여질갯수 and seq_no > 0;

 

이러면 앞부분은 속도가 빠른데 뒷부분은 속도가 느리더군요...흑..

아.. 그리고
커리문을 위처럼 하지 않고
정렬부분을 FST_REG_DT_SORT 키로 하기 위해 힌트만 바꿔서

 

select rnum, seq_no, dir_name, file_name, fst_reg_id, fst_reg_dt, fst_reg_dt_sort
from( select /*+ index_asc(file_upload, FILE_UPLOAD_SORT_IDX) */
seq_no, rownum as rnum, dir_name, file_name, fst_reg_id, fst_reg_dt, fst_reg_dt_sort
from file_upload where FST_REG_DT_SORT > '0' )
where rnum >= ( (선택한 페이지 - 1) * 페이지당보여질갯수 + 1) and rownum <= 페이지당보여질갯수 and FST_REG_DT_SORT > '0';

 

이렇게 커리문을 날리면 윗부분의 커리보다 속도가 더 느려지더군요.
인덱스를 FST_REG_DT_SORT 컬럼에 대하여 생성했는데도.. 흑..
답변주시면 정말 감사하겠습니다.
이것때메 지금..흑..
그럼 안녕히 계세요.

 



이 글에 대한 댓글이 총 3건 있습니다.

저 방법이 많이 사용하는 보편적인 방법이죠.
90% 이상의 유저들이 5페이지 뒷쪽은 거의 안보기 때문이기 합니다만.
말씀하신대로 뒷페이지로 가면 갈수록 쿼리의 효율성이 떨어집니다.

 

모든 페이지에서 일정하게 하는 방법이 있긴 하지만. 정렬의 제약이 있습니다.
그리고 애플리케이션을 조금 변경하셔야 합니다.

 

예) 시퀀스를 기준으로 역순으로 페이징 합니다.

 

글 10개씩 10페이지를 보여준다하면..
seq_no 를 기준으로 글을 101개씩 뽑아옵니다.

그리고 app 에서는 해당 페이지의 글만 10개 리스트로 뿌려줍니다.

 

select /*+ index_desc(seq_no  FILE_UPLOAD_SEQ_NO_PK) */ * from file_upload where rownum < 101

 

그럼 11페이지부터는 어떻게 뽑느냐?
101개의 글을 뽑았으므로 101번째의 시퀀스 넘버를 알고 있겠죠?

 

select /*+ index_desc(seq_no  FILE_UPLOAD_SEQ_NO_PK) */ * from file_upload where seq_no <= 101번째 시퀀스  and rownum < 101

이러면 해당 인덱스에서 원하는 부분만 뽑아올수 있죠.

그리고 시퀀스 넘버를 사용자에게 뿌려주지 않아도 되고

총 글의 갯수를 보여주지 않아도 된다면..

 

select count(*) from file_upload

 

이런 쿼리도 필요가 없어지게 되죠..

--------------------------------------------------------------------

 

쿼리는 예를 들어서 설명한것이니.. 적당히 바꾸어서 사용하세요..

 

동님이 2006-01-23 10:08:31에 작성한 댓글입니다.
이 댓글은 2006-01-23 10:08:55에 마지막으로 수정되었습니다. Edit



엔코아 컨설팅에서 '새로 쓴 대용량 데이타베이스 솔루션 1'

 

에 보면 Paging하는 방법에 대한 설명이 있답니다

(저는 엔코아랑 전혀 관계가 없습니다)

저도 보지는 않고 해당내용이 있다는 얘기만 들었습니다.

 

하여간 원리는

index는 index키 + rowid로 구성이 되어 있습니다.

이원리를 이용하는 것입니다.

row_id 값을 이용하여 크기 비교를 하면서 stopkey를 이용하는

방법입니다.

 

즉 select 절에 rowid컬럼 값을 가져옵니다.

그리고 두번째 페이지는 해당 페이지의 마지막

index + rowid 보다 큰값이 다음 페이지의 시작이 된다는

원리입니다.

김충관(kcg1932)님이 2006-01-23 18:36:06에 작성한 댓글입니다.
이 댓글은 2006-01-23 18:38:01에 마지막으로 수정되었습니다.


rowid 라는건 데이터가 처음 기록이 될때 생기는 주소값인데 그거는 무조건 값이 증가하는 건가요?

그리고 update를 했을경우에 rowid는 변경이 되지 않는건지..

 

rownum처럼 일률적으로 증가한다는 보장이 있다면 괜찮을텐데...

그리고 만약 사용자가 첫번째페이지를 선택했다가 두번째페이지를 선택하지 않고 세번째페이지를 선택했다면 세번째페이지의 시작index키값은 어떻게 알수 있는지요..

오라쿨님이 2006-01-23 21:13:51에 작성한 댓글입니다.
이 댓글은 2006-01-24 09:11:00에 마지막으로 수정되었습니다. Edit