본문 바로가기

DB/SQL

[SQL] 페이징을 위한 ROWNUM과 인라인뷰(@Oracle)

ROWNUM

- Oracle에서는 페이지 처리를 위해서 ROWNUM이라는 특별한 키워드를 사용해서 데이터에 순번을 붙여 사용한다.

- ROWNUM은 SQL이 실행된 결과에 넘버링을 해준다고 생각하면 된다.

- 모든 SELECT문에는 ROWNUM이라는 변수를 이용해서 해당 데이터가 몇 번째로 나오는지 확인할 수 있다.

- ROWNUM은 실제 데이터가 아니라 테이블에서 데이터를 추출한 후에 처리되는 변수이므로 상황에 따라서 그 값이 매번 달라질 수 있다.

 

- SQL에 아무런 조건이 없기 때문에 데이터는 테이블에 섞여 있는 상태 그대로 나오게 된다.(테이블을 FULL 스캔한 것과 동일하다.)

- ROWNUM은 테이블에 존재하지 않고, 테이블에서 가져온 데이터를 이용해서 번호를 매기는 방식으로 결과는 테이블에서 가장 먼저 가져올 수 있는 데이터들을 꺼내서 번호를 붙인다.

- BNO 217번 데이터는 3번째로 꺼내진 데이터이다.

 

 

- 217번 데이터는 3번째로 접근되었지만 정렬 과정에서 뒤쪽으로 밀리는 것을 확인할 수 있다.

- 이를 통해서 알 수 있는 사실은 ROWNUM이라는 것은 데이터를 가져올 때 적용되는 것이고, 이 후에 정렬되는 과정에서는 ROWNUM이 변경되지 않는다는 것이다. == 정렬은 나중에 처리된다.

 

 

INDEX를 이용한 접근 시 ROWNUM

- ROWNUM의 의미가 테이블에서 데이터를 가져오면서 붙는 번호라는 사실은 결국 문제는 테이블에 어떤 순서로 접근하는가에 따라서 ROWNUM값은 바뀔 수 있다는 것이다.

- 위의 경우는 우선  FULL로 접근해서 217번 데이터를 찾았고 이후에 정렬을 하는데 이미 데이터는 다 가져온 상태이므로 ROWNUM에는 아무런 영향을 주지 않는다.

 

- 가장 먼저 찾은 데이터부터 ROWNUM이 1부터 시작

 

 

- PK_BOARD 인덱스 역으로 타면서 테이블에 접근했기 때문에 bno값이 가장 높은 데이터를 가장 먼저 가져오게 된다.

- 이 방식을 이용하면 각 게시물을 정렬하면서 순번은 매겨줄 수 있는데, 1페이지(게시물을 10개씩 페이징하는 경우)에 RN이라는 컬럼의 값이 1부터 10에 해당한다고 볼 수 있다.

 

 

SQL은 아무 결과를 출력하지 않는다...!

- 실행 계획은 안쪽에서부터 바깥쪽으로, 위에서부터 아래로 보게 되므로 위의 실행 계획은 우선 ROWNUM > 10, 데이터들을 찾게 된다.

- 문제는 tb1_board에 처음으로 나오는 rownum의 값이 1이라는 것이다. 

- tb1_board에서 데이터를 찾고 rownum값이 1이 된 데이터는 WHERE 조건에 의해서 무효화가 된다.

- 이후에 다시 다른 데이터를 가져오면 새로운 데이터가 첫 번쨰 데이터가 되므로 다시 rownum은  1이 된ㄷ.

- 이 과정이 반복되면서 rownum의 값은 항상 1이 되고 무효화가 되는 과정을 반복하므로 결과는 아무것도 출력이 되지않는다.

- 이러한 이유로 SQL을 작성할 때 ROWNUM 조건은 반드시 1이 포함되어야 한다.

 

 

ronum 1이 포함되도록 WHERE 조건문을 주면 결과가 출력된다.

 


IN-LINE VIEW (FROM절 서브쿼리)

 

- SELECT문 안쪽 FROM에 다시 SELECT'문

- 인라인뷰는 논리적으로 어떤 결과를 구하는 SELECT문이 있고, 그 결과를 다시 대상으로 삼아서 SELECT하는 것

 

- 데이터베이스에서는 테이블이나 인덱스와 같이 뷰(VIEW)라는 개념이 존재한다.

- VIEW는 일종의 '창문'같은 개념으로 복잡한 SELECT 처리를 하나의 뷰로 생성하고, 사용자들은 뷰를 통해서 복잡하게 만들어진 결과를 마치 하나의 테이블처럼 쉽게 조회한다는 개념이다.

 

- 인라인뷰는 이러한 뷰의 작성을 별도로 작성하지 않고 말 그대로 FROM 구문 안에 바로 작성하는 형태이다.

 

 

20개의 데이터를 가져온 후 2페이지에 해당하는 10개의 결과만을 추출하는 방식으로 구현

 

◆ 정리

- 필요한 순서로 정렬된 데이터에 ROWNUM을 붙인다.

- 처음부터 해당 페이지의 데이터를 'ROWNUM <= 30'과 같은 조건을 이용해서 구한다.

- 구해놓은 데이터를 하나의 테이블처럼 간주하고 인라인뷰로 처리한다.

- 인라인뷰에서 필요한 데이터만을 결과로 남긴다.

'DB > SQL' 카테고리의 다른 글

[SQL] ORDER BY와 INDEX (@Oracle)  (0) 2020.02.18