DESC 인덱스와 오라클 힌트(hint)

전체 상황
상황 : 7,000개의 로우. 회원정보 중 varchar2(4000) 컬럼이 2개 존재.
페이징 : 정렬기준 reg_date desc, mem_id asc (reg_date date, mem_id varchar2(50) )
rank() over (order by reg_date desc, mem_id)


처음 쿼리
SELECT
mem_id,grade,mem_name,gender,phone,email,job,school_region
,school_name,school_grade,school_status,quiz_correct_cnt,cyworld,reg_day
,zipcode,addr1,addr2,self_introduction,act_pledge
FROM(
SELECT rank() over (ORDER BY reg_date DESC, mem_id) rank
,mem_id,grade,mem_name,gender,phone,email,job,school_region
,school_name,school_grade,school_status,quiz_correct_cnt,cyworld,reg_day
,zipcode,addr1,addr2,self_introduction,act_pledge
FROM invite_mem_info
)
WHERE rank BETWEEN (:v1-1)*:v2+1 AND :v1*:v2

=> 엄청난 소요 시간


꼼수
SELECT
a.mem_id,grade,mem_name,gender,phone,email,job,school_region
,school_name,school_grade,school_status,quiz_correct_cnt,cyworld,reg_day
,zipcode,addr1,addr2,self_introduction,act_pledge
FROM(
SELECT rank() over (ORDER BY reg_date DESC, mem_id) rank,mem_id
FROM invite_mem_info
) a, invite_mem_info b
WHERE a.mem_id = b.mem_id
AND rank BETWEEN (:v1-1)*:v2+1 AND :v1*:v2

=> 아이디로만 가져온 테이블과 조인으로 처리. 조금 빨라짐. 하지만 로우개수 늘어나면 마찬가지일 듯.


인덱스 설정
CREATE UNIQUE INDEX idx_invite_mem_info_date_id
ON invite_mem_info(reg_date desc, mem_id);

=> 소용 없었음. 인덱스를 타지 않음.


실험
- 인덱스를 asc로 생성하고 order by ~ asc 는 제대로 빠르다
- 인덱스를 desc로 생성하고 order by ~ desc는 인덱스를 타지 않는다.
- 인덱스를 desc로 생성하면 함수를 타는 것 같다.


해결
인덱스와 힌트를 같이 사용한다.
원하는 형태로 인덱스를 생성하고, 힌트를 이용해 쿼리를 유도한다.
index_asc로 원하는 인덱스트를 타도록 한다.
이때 order by나 rank는 없어도 원하는 형태로 정렬은 되지만 페이지 때문에 rank는 계속 사용했다.

INDEX
CREATE UNIQUE INDEX idx_invite_mem_info_date_id
ON invite_mem_info(reg_date desc, mem_id);

QUERY
SELECT /*+ index_asc(invite_mem_info idx_invite_mem_info_date_id)*/
mem_id,grade,mem_name,gender,phone,email,job,school_region
,school_name,school_grade,school_status,quiz_correct_cnt,cyworld,reg_day
,zipcode,addr1,addr2,self_introduction,act_pledge
FROM(
SELECT rank() over (ORDER BY reg_date DESC, mem_id) rank
,mem_id,grade,mem_name,gender,phone,email,job,school_region
,school_name,school_grade,school_status,quiz_correct_cnt,cyworld,reg_day
,zipcode,addr1,addr2,self_introduction,act_pledge
FROM invite_mem_info
)
WHERE rank BETWEEN (:v1-1)*:v2+1 AND :v1*:v2