MySQL의 Query Cache는 쿼리 블록 단위로 캐싱이 가능할까?

MySQL은 Query Cache 기능을 제공합니다. 이 기능은 쿼리 수행 결과를 메모리에 저장한 후에, 동일한 SQL이 수행되면 메모리에 저장된 수행 결과를 리턴하는 기능입니다.
쿼리 수행 대신 메모리에 있는 수행 결과를 리턴해주므로 수행 속도는 매우 빠릅니다. ORACLE 11g부터 제공하는 Result Cache의 Subset이라고 보면 될 것 같습니다.

이 기능을 잘 활용할 수 있는 업무는 주로 게시판 카운트 쿼리입니다. 특히, 입력 빈도는 높지 않으나 조회 빈도가 높은 게시판인 경우에는 Query Cache의 효과가 크겠죠.
또한, 편법이기는 하지만 임원들이 자주 보는 화면의 특정 조건 쿼리에 쿼리 캐시를 적용하면, 업무 담당자들이 스트레스가 조금은 줄어들 것 같습니다.

제가 MySQL의 쿼리 캐시에 대해서 궁금했던 점은 ORACLE과 같이 쿼리 블록 단위로도 캐싱이 가능한지 였습니다. 결론부터 말하면 안되네요. 사실, UI 화면은 매우 복잡하고 다양한 검색 조건이 존재합니다. 그리고 속도가 느린 쿼리의 대부분은 복잡한 쿼리겠죠. 하지만 간혹 이런 쿼리들의 공통 분모(쿼리 블록)가 존재하고, 이 부분이 항상 느리다면 쿼리 캐시 기능이 매우 좋은 해결책이 됩니다. 하지만 MySQL은 아쉽게도 이 부분은 지원되지 않고 있습니다. 아래의 테스트 내용을 참고하세요.

— 파라미터 설정

query_cache_size=10485760

-- 0:off 1: 항상 enable 2: on demand (SQL CACHE 힌트 사용시 사용)
query_cache_type=2

— 확인

mysql> show variables like 'query_cache%';
+------------------------------+----------+
| Variable_name                | Value    |
+------------------------------+----------+
| query_cache_limit            | 1048576  |
| query_cache_min_res_unit     | 4096     |
| query_cache_size             | 10485760 |
| query_cache_type             | DEMAND   |
| query_cache_wlock_invalidate | OFF      |
+------------------------------+----------+

— 조회 속도가 느림

mysql> select count(*) from t1;
+----------+
| count(*) |
+----------+
| 36500000 |
+----------+
1 row in set (23.66 sec)

— 쿼리 캐시를 적용함

mysql> select SQL_CACHE count(*) from t1;
+----------+
| count(*) |
+----------+
| 36500000 |
+----------+
1 row in set (23.42 sec)

— 캐시된 결과를 리턴하므로 매우 빠름

mysql> select SQL_CACHE count(*) from t1;
+----------+
| count(*) |
+----------+
| 36500000 |
+----------+
1 row in set (0.00 sec)

— 관련 Stat 수치가 증가하는 것을 확인할 수 있음

mysql> show status where Variable_name like 'Qcache_hits%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Qcache_hits   | 3     |
+---------------+-------+

— 대소문자를 구분함

mysql> SELECT SQL_CACHE count(*) from t1;
+----------+
| count(*) |
+----------+
| 36500000 |
+----------+
1 row in set (21.67 sec)

— 스페이스도 구분함

mysql> SELECT  SQL_CACHE count(*) from t1;
+----------+
| count(*) |
+----------+
| 36500000 |
+----------+
1 row in set (22.73 sec)

— 쿼리 블록 단위로는 사용이 불가능함.

mysql> select max(c1) from (select SQL_CACHE count(*) c1 from t1) a;
ERROR 1234 (42000): Incorrect usage/placement of 'SQL_CACHE'

테이블에 변경이 생기면 Query Cache는 Invalid 상태가 됨

mysql> delete from t1 limit 1;

mysql> select SQL_CACHE count(*) from t1;
+----------+
| count(*) |
+----------+
| 36499999 |
+----------+
1 row in set (23.03 sec)

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s