[MySQL] 전체 목록(row) count DB 부하 없이 빠르게 불러오는 팁!

2017-05-25
웹 개발 이야기

작성일자: 2017-05-25 14:02:12
최종수정: 2017-05-25 16:04:47
Link: http://blog.jeehooo.net/16



  


전체 게시글 수, 전체 댓글 수, 전체 접속자 수...
이렇게 전체 목록의 카운트를 불러낼 때 보통 아래와 같이 select count문을 많이 사용하게 되는데요.
 
select count(column) as count from table;

뭐.. 테이블 상태, 서버 스펙, 엔진(MyISAM/InnoDB) 등 여러가지 변수가 있기 때문에 '이거다' 하고 결론 내리긴 그렇지만...
이런 방법으로 전체 카운트를 구할 경우, DB를 한번 쭉 쓸어줘야 결과가 나오기 때문에
데이터가 쌓이게 된다면 전체 카운트를 얻기 위해 어마무시한(?) 시간이 소요되는 경우가 생기게 됩니다.



▲그렇게 접속자가 많지 않은 사이트인데도 몇 년 방치해놓으면 21만건이라는 어마어마한 기록이 쌓입니다ㄷㄷ





제 블로그의 카운터를 가지고 예를 들어볼께요.
현재 접속자, 오늘, 어제, 총 접속자, 그리고 검색 로봇이 몇 마리 들어왔는지 보여줍니다.
총 접속자의 경우 접속 로그 테이블의 총 row 수를 보여주는데, 대부분 여기서 select count 문을 사용하게 됩니다.

구글링을 해보니 count(*)이 빠르다, 트리거를 써라, 주기적으로 캐싱을 하라는 등 많은 방법이 나왔지만 다들 만족스러운 방법은 아니었던게,
아무리 최적화를 한다고 해도 페이지가 열릴 때 마다 테이블 전체를 읽어야 한다는 것 자체가 별로였고
캐싱이나 트리거 역시 복잡한 것에 비해 얻는게 상대적으로 적다고 느껴졌기 때문이었습니다.



그래서 저는 show table status 에 나오는 rows 값을 사용했습니다.
이렇게 하면 select 한 번만 돌리면 row값을 알 수 있어 DB 부하를 줄일 수 있기 때문입니다.

물론 실제로 count를 돌린 값이 아니기 때문에 상황에 따라 오차가 발생할 수는 있지만,
오차가 1도 없어야 하는 정확한 값이 필요하지 않은 경우 유용하게 사용할 수 있죠.
사용자에게 보여주는 전체 게시글 수나 방문자 수에 정확한 값을 줄 필요는 없으니까요.




show table status 에서 나오는 데이터는 아래와 같은 구조를 가지고 있는
information_schema 라는 데이터베이스의 TABLES에서 동일한 값을 가져올 수 있습니다.

이 중에서 TABLE_SCHEMATABLE_NAME 값을 조건으로 TABLE_ROWS 를 가져오는 쿼리를 만들면 되겠죠?



TABLE_SCHEMA : 데이터베이스 이름
TABLE_NAME : 빨간 밑줄 부분이 테이블 이름입니다.
TABLE_ROWS : 전체 row 수

TABLE_NAME의 경우 다른 값이 섞여 있으니, Like 문을 사용해야 하며, 나머지 값의 경우 그대로 가져다 사용하면 됩니다. 

결론적으로 아래와 같은 쿼리를 만들 수 있겠네요.
 
select TABLE ROWS from information_schema.TABLES where TABLE_SCHEMA = 'jeehooo_blog' and TABLE_NAME like 'log';

위 쿼리문에서 jeehooo_blog원하는 데이터베이스, log테이블 이름으로 바꿔서 사용하시면 됩니다.