본문 바로가기
스터디/오라클 성능고도화 원리와 해법1

05.데이터베이스 Call 최소화 원리 - 06. 페이지 처리의 중요성

by 취미툰 2020. 2. 2.
반응형

클라이언트/서버 환경에서 대용량 데이터를 조회할 때는 커서를 닫지 않은 채 사용자 이벤트(스크롤 바를 내리거나 ‘다음’버튼을 클릭 하는 행위 등)가 발생할 때마다 결과 집합을 Fetch하도록 구현할 수 있었습니다.
웹 애플리케이션 환경에서는 커서를 계속 오픈한 채로 결과집합을 핸들링할 수 없습니다. 즉, 데이터베이스와의 연결을 지속하지 않는 웹 환경이기 때문에 사용자가 다음 페이지를 요청하거나 스크롤 바를 내릴때 마다 개벼럭인 SQL문을 수행하는 방식으로 페이지 처리를 구현해야 합니다. 그러다 보니 페이지 처리 구현 방식이 자주 이슈가 되곤 합니다.

i := 0;
loop
fetch c into l_record;
exit when (c%notfound or (i = pageNo * pageSize));
i := i + 1;
if i > (pageNo-1)*pageSize then
printRow(l_record);
end if;
end loop;

위는 실제로 화면 페이지 처리를 구성할때 사용했던 PL/SQL입니다. 데이터를 계속 fetch하다가 출력해야 할 페이지에 도달하면 그때부면 printRow를 호출해 pageSize개수만큼의 로우를 출력하고, 그제야 fetch를 멈춥니다. 해당 쿼리는 뒤 페이지로 갈수록 엄청나게 많은 fetch call을 유발하게 되고, 전반적으로 이런 스타일로 구현했다면 시스템에 많은 부하를 일으키게 됩니다.
fetchSize를 늘리면 어떨까요? 뒤 페이지를 클릭할 때 발생하는 불필요한 Fetch Count는 줄일 수 있습니다. 하지만 Array 버퍼에 쌓인 다량의 로우를 읽으면서 발생하는 CPU리소스 낭비는 여전하고 메모리 사용량은 늘어날 것이며 앞쪽 페이지를 출력할 때는 서버로부터 불필요하게 많은 로우를 가져와야 하므로 서버 및 네트워크 부하를 가중시켜 상황이 더 안 좋아질지도 모릅니다.
유일한 해결책은 페이지 처리를 서버 단에서 완료하고 최종적으로 출력할 레코드만 fetch 하도록 고치는 것입니다.

다른 예로는 시스템 전체적으로 아예 페이지 처리 없이 개발하는 예도 있습니다. 이 경우는 대량의 결과 집합을 페이지 처리 없이 모두 출력하도록 구현하므로 시스템 전반에 일으키는 부하는 엄청 큽니다.
- 대량의 fetch Call 발생(SQL*NET roundtrips to/from client)
- 대량의 결과집합을 클라이언트로 전송하면서 발생하는 네트워크 부하(bytes sent via SQL*NET to client)
- 대량의 데이터 블록을 읽으면서 발생하는 I/O 부하
- AP서버 및 웹 서버 리소스 사용량 증가
이렇게 여러가지 부하를 일으키지만 사용자는 정작 앞쪽 일부 데이터만 읽고 업무처리를 완료하는 경우가 대부분이며, 쿼리 자체 성능도 문제지만 시스템 전반적으로 불필요한 리소스를 낭비하게 되므로 더 큰 문제입니다.
이를 해결하기 위한 페이지 처리 tip
- 페이지 단위로, 화면에서 필요한 만큼씩 fetch Call
- 페이지 단위로, 화면에서 필요한 만큼씩 네트워크를 통해 전송
- 인덱스와 부분범위처리 원리를 이용해 각 페이지에 필요한 최소량만 I/O
- 데이터를 소량씩 나누어 전송하므로 AP, 웹 서버 리소스 사용량 최소화

일반조회시에는 페이지 처리를 하고, 사용자가 필요할 때만 ‘전체조회’ 또는 ‘다운로드 받기’버튼을 클릭할 수 있도록 기능을 제공하는 것이 바람직합니다.

반응형

댓글