백엔드에서 Paging을 구현할 때,
limit offset 구조로 제한된 row의 개수를 가지고 온다
여기서 페이징을 구현을 위한 계산을 하기 위해 조회된 row 의 전체 건 수가 필요하게 되는데,
언제나 완벽한 쿼리를 작성할 수 없기 때문에, 성능적으로 좋지 않은 경우가 있다
이런 경우, limit로 제한한 데이터의 건수와 전체 데이터 건 수를 각각 호출하여 데이터를 불러올 때,
count() 함수를 이용하여 데이터를 가져오면 데이터를 가져오는 시간보다 타임아웃이 더 길게 걸릴 수 있다
물론 쿼리 튜닝을 진행하면 좋겠지만, 상황 상 튜닝을 할 여유가 없다면 해당 방법으로 전체 건수를 가져오는 것도 좋은 방법이라고 생각한다
이번 포스팅에서는 Mybatis 환경에서 페이징 처리를 하는 데이터의 전체 건수를 가지고 오는 방법에 대해 포스팅 할 예정이다
SELECT SQL_CALC_FOUND_ROWS ... FROM ... WHERE ... LIMIT 10;
SELECT FOUND_ROWS();
조회하려는 SELECT 쿼리문에 SQL_CALC_FOUND_ROWS 옵션을 붙여주게 되면 전체 row 수를 임시저장하고,
FOUND_ROWS() 명령문에서 전체 쿼리에 대한 행 수를 반환해준다
예를 들어 쿼리 내부에 limit 20 offset 0 를 지정해서 20건씩 데이터를 가지고 온다해도, 해당 쿼리에서 조회되는 전체 데이터 수가 200건이라면 FOUND_ROWS() 에서는 200을 리턴해준다
간단한 사용 예제를 보여주면 다음과 같다
<sql id="sql_ratingList">
-- SQL_CALC_FOUND_ROWS는 FOUND_ROWS()를 사용할 때만 명시해준다 SELECT SQL_CALC_FOUND_ROWS *
FROM user A
INNER JOIN study B ON A.id = B.id
LEFT OUTER JOIN books C ON B.book_id = C.book_id
WHERE 1=1
AND A.type="U"
AND C.status = 1000
</sql>
|
cs |
예를 들어, 위와 같은 쿼리가 있다면, 해당 쿼리의 limit 데이터와 전체 건수를 가져오는 SQL 쿼리를
FOUND_ROWS() 를 사용했을 때와 사용하지 않았을 때의 방법으로 구현하면 다음과 같다
-- 사용했을 때
<select id="totalCnt" resultType="Int">
SELECT FOUND_ROWS() AS "total"
</select>
-- 사용하지 않았을 때
<select id="totalCnt" resultType="Int">
SELECT COUNT(1)
FROM (<include refid="list" />) A -->
</select>
|
cs |
위의 예제 쿼리는 쿼리 구조가 단순하고 쉽기 때문에, 어떤 방법으로든 데이터를 가져오는 시간이 그렇게 오래 걸리지 않을 것이다
하지만,
쿼리구조가 복잡해지고, 성능을 고려하지 않은 쿼리가 작성되었을 때 count() 건 수를 가져오려면 시간적으로 많은 비용이 발생할 수 있다
그래서 쿼리 성능을 개선할 시간이 없거나 할 여견이 되지 않는다면, FOUND_ROWS() 를 사용하는 것도 고려해보자
주의 사항
다음은 Mysql 8 버전 레퍼런스에서 볼 수 있는 해당 기능에 대한 설명이다
다음을 보면 8.0.17 이후부터 다음 기능이 제거될 것으로 예상된다는 말을 한다
고려해서 사용하자 ~!
'개발 > BACK' 카테고리의 다른 글
[JAVA] Mysql GROUP_CONCAT 데이터 int 타입으로 변경하기 (0) | 2022.08.15 |
---|---|
[SpringFramework] 마이바티스 환경에서 INSERT,UPDATE 무시하기 (0) | 2022.08.15 |
[Ubuntu] 서버 Tomcat 꺼지면 재시작하는 스크립트 작성하기 (0) | 2022.05.23 |
[Ubuntu] Linux 에서 톰캣 재시작 스크립트 작성하기 (0) | 2022.05.23 |
[SpringFramework] 게시판 페이징 기능 예제 ,쉽게 페이징을 구현하자 (0) | 2022.05.10 |