[꼼꼼한 개발자] 꼼코더
41. 코드로 배우는 스프링 웹 프로젝트 - [페이징 처리] - 오라클데이터 베이스 페이징 처리, order by의 문제, 실행 계획, SQL 실행 단계 알아보기 본문
41. 코드로 배우는 스프링 웹 프로젝트 - [페이징 처리] - 오라클데이터 베이스 페이징 처리, order by의 문제, 실행 계획, SQL 실행 단계 알아보기
꼼코더 2023. 1. 28. 21:45📄 오라클데이터 베이스 페이징 처리
현재 가장 미숙한 부분은 목록 페이지이다.
기본적으로 페이징(pagination) 처리가 필요하다.
(수많은 데이터를 한 페이지에 보여주면, 처리 성능에 영향을 미치기 때문)
페이징 처리는 크게 ‘번호’를 이용하거나 ‘계속보기’의 형태로 구현된다.
번호를 이용한 페이징 작업 : 과거 웹 초기부터 이어오던 방식
계속보기를 이용한 페이직 작업 : Ajax와 앱이 등장한 이후에 ‘무한 스크롤’이나 ‘더 보기’와 같은 형태로 구현.
예제는 전통적인 번호를 이용하여 처리한다.
오라클에서 페이징 처리하는 것은 MySQL에 비해 추가적인 지식이 필요하므로
이에 대한 학습을 선행해야 한다.
🚨 order by의 문제
데이터의 양이 많을수록 프로그램을 이용해 정렬이라는 작업을 사용한다
하지만 데이터베이스 경우 수만 개의 데이터를 처리하기 때문에
많은 시간과 리소스를 소모하게 된다.
데이터베이스를 이용한 웹이나 애플리케이션에서 가장 신경 쓰는 부분 2가지는
1) 빠르게 처리되는 것
2) 필요한 양 만큼만 데이터를 가져오는 것
예시로 거의 모든 웹페이지에서 페이징을 하는 이유는
최소한의 필요한 데이터만을 가져와서 빠르게 화면에 보여주기 위함이다.
빠르게 동작하는 SQL을 위해서는 가능한 order by를 이용하는 작업을 하지 말아야 한다.
데이터가 많은 경우 엄청난 성느의 저하를 가져오기 때문이다
👀 order by를 어떨때 사용해야 할까?
1) 데이터가 적은 경우
2) 정렬을 빠르게 할 수 있는 방법이 있는 경우
✍🏻 실행 계획과 order by
오라클의 페이징 처리를 제대로 이해하려면 실행 계획(execution plan)을 반드시 알아야 한다.
말 그대로 ‘SQL을 데이터베이스에서 어떻게 처리할 것인가?’에 대한 것
SQL이 데이터베이스에 전달되면 데이터베이스는 여러 단계를 거쳐서
해당 SQL을 아래와 같은 순서와 과정을 거쳐서 처리한다.
실행 계획을 간단하게 정리하자면
“SQL을 전달하면 데이터베이스에서 처리순서가 어떻게 결정되지? 나는걸 눈으로 확인하는 것”이 실행 계획
SQL 파싱단계
- SQL 구문에 오류가 있는지
- SQL을 실행해야 하는 대상 객체가 존재하는지 검사(테이블, 제약 조건, 권한 등)
SQL 최적화 단계
- SQL이 실행되는데 필요한 비용(cost)을 계산
- 이 계산 값을 기초로 가장 좋은 방식을 판단하는 ‘실행 계획’을 세우게 된다.
SQL 실행 단계
- 세워진 실행 계획을 통해서 메모리상에서 데이터를 읽거나 물리적인 공간에서 데이터 로딩하는 등의 작업을 하게 된다.
- 개발자들은 도구를 이용하거나 SQL Plus 등을 이용해서 특정한 SQL에 대한 실행 계획을 알아볼 수 있다.
🔍 SQL 실행 단계 알아보기
SQL Developer에서는 간단히 버튼을 클릭하여 실행 계획을 확인할 수 있다.
예시로 ‘게시물 번호를 역순으로 출력하라’는 처리를 한다면
SQL Developer에서 다음과 같이 처리할 수 있다.
상단 버튼 중에 SQL에 대해서 ‘실행 계획’을 쉽게 볼 수 있도록 버튼이 제공된다.
실행 계획을 보면 트리구조로 방금 전 실행한 SQL이 어떻게 처리되는지 알려준다
실행 계획에 대해서 많은 내용을 설명할 수 없지만
간단하게 실행 계획을 보는 방법은 ‘안쪽에서 바깥쪽으로, 위에서 아래로’ 봐주면 된다.
위 그림을 보면 PK_BOARD라는 것을 이용해서 접근하고 스캔하여 정렬했다는 것을 의미
실행 계획을 세우는 것은 데이터베이스에서 하는 역할이기 때문에
데이터의 양이나 제역 조건등의 여러 상황에 따라서 데이터베이스는 실행계획을 다르게 작성한다.
테스트를 위해 데이터가 좀 많아지도록 아래의 SQL을 여러번 실행해서
데이터를 수백 만개로 반든 후에 커밋을 하자.
위에 insert문을 여러번 실행 시 tbl_board 테이블의 데이터 수만큼 다시 insert가 진행된다.
결과를 보면 2배씩 늘어나는 걸 확인할 수 있다.
commit 후에 ‘select count(*) from tbl_board’ 실행해 보면
엄청난 데이터의 수를 확인할 수있다.
데이터가 많아지면 그만큼 정렬에 많은 시간을 소모하게 된다.
고의적으로 bno라는 칼럼의 값에다 1을 추가한 값을
역순으로 정렬하는 SQL을 만든다면 다음과 같다.
연산 작업이 추가되기는 하지만 SQL문 결과가 나오는데 1.147초가 나온다
SQL을 실행한 결과인 위에 그림을 보면 테이블 전체를 스캔(조사)하는 것을 볼 수 있다.
실행계획을 잠깐 봐보자면 TBL_BOARD를 ‘FULL’로 조사(스캔)했고
바깥쪽으로 가면서 ‘SORT’가 일어난 것을 볼 수 있다.
이때 가장 많은 시간을 소모하는 작업은 정렬하는 작업이다.
위에 SQL에서 ‘order by bno + 1 desc’라는 조건에서 ‘+1’을 하는 것은
정렬에 아무런 도움을 주지 않는다 따라서 아래와 같이 SQL을 수정해서 실행하자.
연산이라는 차이가 있지만 실행 시간은 매우 차이가 난다.(10배 정도)
이 결과의 차이에는 실행 계획도 기존과 다르게 동작한다.
기존 SQL이 TBL_BOARD 테이블 전체를 스캔했지만
이번에는 PK_BOARD라는 것을 이용해서 접근하고
기존과 달리 맨 위의 SORT 과정이 없는 것을 볼 수 있다.
이것을 이해하려면 데이터베이스의 인덱스(index)에 대해서 조금은 알아둘 필요가 있다.