본문 바로가기

개발/BACK

[Mysql] limit 페이징에서 쿼리 조회 건 수 구하기 SQL_CALC_FOUND_ROWS

728x90

 


백엔드에서 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 이후부터 다음 기능이 제거될 것으로 예상된다는 말을 한다

 

고려해서 사용하자 ~!

 

 

728x90