MySQL : SQL_CALC_FOUND_ROWS()

SQL_CALC_FOUND_ROWS는 SELECT 쿼리에 사용되는 MySQL 힌트로

SELECT 쿼리에 의해 반환되는 전체 row의 개수를 임시로 저장하게 하는 역할을 합니다.

만약, SELECT 쿼리에 LIMIT절이 포함되어 있는 경우에는

LIMIT절을 적용하지 않은 전체 row의 개수를 임시로 저장합니다.

임시로 저장된 row의 개수는

SELECT FOUND_ROWS() 가 실행될 때 반환됩니다.

 

SQL_CALC_FOUND_ROWS와 관련된 자세한 사항은 아래의 링크를 참고하십시요.

http://www.mysqlkorea.co.kr/sub.html?mcode=develop&scode=01&lang=k&m_no=21838&cat1=12&cat2=359&cat3=374

 

예를 들어, 게시판에서 페이징을 구현할 때엔

일반적으로 페이징을 하기 위해 전체 게시물의 개수를 알기 위한 SELECT COUNT(*) 쿼리와

화면에 표시되는 (특정 영역의) 데이터를 SELECT 하기 위한 쿼리를

별도로 작성하여 실행하게 됩니다.

 

같은 조건을 갖는 두 개의 쿼리를 별도로 작성하기 위해 소스 코드가 복잡해지는 경우가 많은데,

SQL_CALC_FOUND_ROWS를 사용하면 하나의 쿼리를 사용하여 깔끔하게 구현할 수 있게 됩니다.

 

MySQL 매뉴얼에 의하면, SQL_CALC_FOUND_ROWS을 사용할 경우

그렇지 않은 경우에 비해 속도가 빨라진다고 했는데,

작업을 하다 보니 이상한 점이 있어 간단히 테스트를 해 보았습니다.

 

테스트에 사용된 테이블의 전체 건수는 32,959건이었고, row의 평균 크기는 431 byte였습니다.

 

소스를 살짝 변경하여

아래와 같이 3가지 유형으로 운영되었을 때의

MySQL 서버의 CPU 사용률, MySQL 네트워크 트래픽(sent), 웹 페이지 로딩 시간을 각각 측정해 보았습니다.

(측정값은 최대값의 근사치입니다.)

 

유형1. SELECT + mysql_data_seek()

LIMIT절을 사용하지 않고 SELECT를 실행한 후,

소스 코드에서 mysql_data_seek()를 사용하여 특정 위치의 데이터에 접근(점프)하여 화면에 표시하는 방식

(전체 게시물의 건수를 알기 위한 별도의 SELECT COUNT(*) 쿼리를 사용하지 않음)

 

유형2. SELECT COUNT(*) + SELECT ~ LIMIT

가장 일반적인 방식으로 전체 게시물 건수를 알기 위한 SELECT COUNT(*) 쿼리와

특정 영역의 데이터를 표시하기 위한 SELECT ~ LIMIT 쿼리를 별도로 작성하여 실행하는 방식

 

유형3. SELECT SQL_CALC_FOUND_ROWS ~ LIMIT

SQL_CALC_FOUND_ROWS를 사용하여 한번에 SQL을 작성하여 실행하는 방식

 

테스트 결과

MySQL 서버 CPU 사용률 MySQL 네트워크 트래픽 웹 페이지 로딩시간
유형1 : SELECT + mysql_data_seek() 41% 1.2 MB 0.83 sec
유형2 : SELECT COUNT(*) + SELECT ~ LIMIT 11% 15.5 kb 0.36 sec
유형3 : SELECT SQL_CALC_FOUND_ROWS ~ LIMIT 27% 15.6 kb 0.65 sec

* 각 수치는 유형간의 상대치로 생각해 주시기 바랍니다.

 

테스트를 해 본 결과, MySQL 매뉴얼의 내용과 달리

SQL_CALC_FOUND_ROWS를 사용(유형3)했을 때

기존의 방식(유형2)에 비해 전체적으로 성능이 저하된다는 것을 알 수 있었습니다.

그러나 유형1의 방식에 비해서는 훨씬 좋은 성능을 보여 주었습니다.

 

SQL_CALC_FOUND_ROWS를 사용했을 때 성능이 저하되는 원인은 아래의 링크를 참고하십시요.

http://www.mysqlperformanceblog.com/2007/08/28/to-sql_calc_found_rows-or-not-to-sql_calc_found_rows/

 

테스트 결과 상으로는 SQL_CALC_FOUND_ROWS를 사용하는 것이 불리하지만,

운영환경에 따라 불리함의 의미가 달라질 수도 있을 것 같습니다.

 

테스트를 진행할 때는 각각의 실행 결과를 정확히 알기 위해

MySQL의 Query Cache 기능을 제한하였는데,

Query Cache 기능을 활성화한 상태에서 Query Cache에 cache된 내용이 사용되는 경우에는

유형2와 유형3의 성능이 거의 같게 나왔습니다.

 

따라서 Query Cache의 사용률이 높은 환경이라면,

SQL_CALC_FOUND_ROWS를 사용하여 소스의 복잡도가 낮추는 것이

훨씬 유용하지 않을까 생각됩니다.

출처 : Tong – 쌈닭님의 04.MySQL통

[출처] SQL_CALC_FOUND_ROWS|작성자 삼오사삼

CC BY-NC-SA 4.0 This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.