신입 개발자가 되기 위해 공부했던 독학 자료들/Oracle

[오라클] 상위 n개 데이터 가져오기 (RANK OVER() 함수 또는 INDEX 사용)

Seojoo21 2022. 3. 25. 17:21

아래 쿼리문은 tbl_board에서 추천수와 조회수가 가장 많은 게시물을 기준으로 정렬한 테이블을 인라인 뷰로 하여 상위 5개 게시물만 가져오는 쿼리문이다.

SELECT BNO, TITLE, WRITER, LIKEHIT
FROM
(SELECT BNO, TITLE, WRITER, LIKEHIT, VIEWHIT, 
RANK() OVER (ORDER BY LIKEHIT DESC, VIEWHIT DESC) AS RANK FROM TBL_BOARD)
WHERE RANK <= 5;

 

위의 쿼리문에서 인라인뷰에 해당하는 아래 쿼리문을 살펴보면 RANK() OVER 함수를 쓴다는 것을 알 수 있다. 

SELECT BNO, TITLE, WRITER, LIKEHIT, VIEWHIT,
RANK() OVER (ORDER BY LIKEHIT DESC, VIEWHIT DESC) AS RANK FROM TBL_BOARD

그런데 RANK() OVER 함수의 경우 DB 전체를 조회하여 순위를 결정하므로 데이터가 많아질 경우 성능이 저하될 수 있다. 

그래서 이번 케이스의 경우 RANK() OVER 대신 인덱스를 이용하여 쿼리문을 개선해볼 수 있다. 

 

일단 추천수와 조회수를 기준으로 정렬할 수 있는 인덱스를 만든다. 

CREATE INDEX IDX_BOARD_LIKE ON TBL_BOARD (LIKEHIT, VIEWHIT);

그리고 위의 인덱스를 이용해서 아래와 같이 INDEX_DESC 힌트문을 작성한다.  

SELECT /*+INDEX_DESC(TBL_BOARD IDX_BOARD_LIKE)*/ 
BNO, TITLE, WRITER, LIKEHIT, VIEWHIT FROM TBL_BOARD;

그럼 아래와 같이 앞서 RANK() OVER 함수를 사용했을 때와 동일한 결과를 얻을 수 있다. 하지만 수행 시간이 0.001초 더 빠르다는 것을 알 수 있다. 지금은 데이터가 얼마 없어서 별 차이가 없지만 데이터가 많아지면 이 속도 차이는 더 커진다. 

따라서 최종적으로 맨 처음 작성했던 쿼리문을 아래와 같이 수정하여 사용할 수 있다. 

SELECT BNO, TITLE, WRITER, LIKEHIT
FROM
(SELECT /*+INDEX_DESC(TBL_BOARD IDX_BOARD_LIKE)*/ 
BNO, TITLE, WRITER, LIKEHIT, VIEWHIT FROM TBL_BOARD)
WHERE ROWNUM <= 5;

 

도움 받은 글:

https://coding-factory.tistory.com/419

https://gent.tistory.com/306

http://www.joshi.co.kr/index.php?mid=board_MfJr34&document_srl=292221 

https://gent.tistory.com/266

https://gent.tistory.com/477