Paging쿼리 문의 드립니다. 1 6 1,962

by 동동동 [SQL Query] [2016.08.23 13:35:38]


With AA As (
Select '001' CODE, '홍길동' NAME From Dual Union All
Select '004' CODE, '김길동' NAME From Dual Union All
Select '002' CODE, '홍석동' NAME From Dual Union All
Select '005' CODE, '이순신' NAME From Dual Union All
Select '003' CODE, '구마동' NAME From Dual Union All
Select '006' CODE, '신길동' NAME From Dual Union All
Select '007' CODE, '박길동' NAME From Dual
)
Select * From (
Select row_number() over (order by NAME) as RowNo,
       AA.*
 From AA
 Where 1 = 1    
  And NAME Like '%동'
  --And CODE > :LASTCODE    --Order By가 Name이다보니 선 필터링을 못함..
  )
 Where Rowno >= ((:PAGENO - 1) * :ROWCNT + 1)
   And RowNo <= (:PAGENO * :ROWCNT);
   
--ROWCNT = 2,    PAGENO = 1

 

1억건 이상의 데이타 인데요..다음과 같이 이름으로 조회시 Code가 Unique인데 보여줄때는 이름순으로 보여줘야 해서 중간에 Code로 필터링을 못하고 있습니다.

뭔가 좋은 방법이 없을련지요??

 

by lovekod2hj [2016.08.23 13:52:42]

NAME Like '%동' 조건이 NAME 컬럼 인덱스를 만들어 준다고 해도 인덱스를 이용하지 못하기 때문에 FULL 스캔이 될 수 밖에 없습니다. INDEX를 이용할 수 있는 검색조건을 추가할 수 있는지 우선 검토해 보시는게 좋을 거 같습니다.


by 동동동 [2016.08.24 14:58:27]

답변 감사드립니다...

아..예제에서만 %Name입니다..^^

실제로는 Name을 인덱스 할수있게 했습니다..


by 마농 [2016.08.23 14:19:07]

정확한 정렬 및 페이징을 위해서는
  order by 기준에 중복되는 name 외에 유니크한 code 또는 Rowid 등이 추가되어야 합니다.
  중복값으로 정렬시 페이징이 이상해 질 수 있습니다.


성능향상을 위해서는
  name 인덱스가 필요해 보입니다.
  aa.* 로 테이블의 모든 항목을 가져오기 보다는
  인덱스 항목인 name 과 ROWID 만을 가져와 페이징하는게 좋습니다.
  기타 필요 항목은 페이징 완료후에 테이블 조인하여 가져오면 됩니다.


다음 페이지 가져오기 방법을 이용하기 위해서는
  last_code 가 아닌 last_name 과 last_rowid 항목을 이용해야 합니다.
  AND ( (name = :last_name AND ROWID > :last_rowid) OR (name > :last_name) )


다음 강좌 참고하세요.
  http://www.gurubee.net/expert/kwontra
  6. 목록 쿼리를 최적화하자.


by 동동동 [2016.08.24 15:00:39]

마농님 답변 감사드립니다..

그런데 Rowid는 데이타가 입력된 순서데로 증가값이 들어가게 되는게 아닌지요??

이름으로 정렬시 다음페이지에서 보여줘야할 정보에 첫페이지에서 보여준 Rowid보다 작은 Rowid가 존재할 수 있는데.. 그것 때문에 or name > :last_name를 조건으로 주신 건지요?

(name = :last_name AND ROWID > :last_rowid) OR (name > :last_name)


by 마농 [2016.08.24 15:09:19]

이름은 중복이 가능하기 때문에

중복 안되는 ROWID 를 정렬조건에 추가해 주는 것입니다.

정렬키는 (이름, Rowid) 가 되는 거구요.

키가 하나일 때와 달리 두개 일 때는 조건이 좀 복잡해 지는 거죠.


by 동동동 [2016.08.24 16:24:22]

답변 감사드립니다..

인라인뷰에서 And (name = :last_name AND ROWID > :last_rowid) OR (name > :last_name)를

사용할 경우에는

 Where Rowno >= ((:PAGENO - 1) * :ROWCNT + 1)
   And RowNo <= (:PAGENO * :ROWCNT); 대신에

 Where RowNo <= :ROWCNT; 만 사용해야 겠군요..^^

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입