ProxySQL Query Caching - 데이터베이스 부하를 줄이는 실전 캐시 전략
대규모 트래픽을 처리하는 서비스라면, DB 성능은 곧 사용자 경험과 직결됩니다. 오늘은 ProxySQL의 핵심 기능 중 하나인 Query Caching에 대해 정리해보겠습니다. 실제 현업에서 사용해본 입장에서 장단점과 세팅 포인트까지 함께 공유드릴게요.
✅ ProxySQL Query Caching이란?
ProxySQL은 MySQL과 애플리케이션 사이에 위치한 고성능 SQL 프록시 서버입니다. Query Caching 기능은 특정 쿼리 결과를 ProxySQL 자체 메모리에 저장하고, 동일한 쿼리가 반복될 경우 DB가 아닌 ProxySQL이 직접 응답하게 만듭니다.
즉, 자주 호출되는 SELECT 쿼리에 대해 쿼리 성능은 빨라지고, DB 부하는 줄어드는 효과를 기대할 수 있습니다.
💡 어떤 원리로 동작할까?
- 사용자가 쿼리를 전송하면 ProxySQL이 이를 검사합니다.
- 이전에 동일한 쿼리가 실행되었고, TTL(Time-To-Live) 이내라면?
- DB로 전달하지 않고, ProxySQL의 메모리 캐시에서 결과를 바로 반환합니다.
- 캐시가 없다면 DB로 요청을 전달하고, 결과를 캐싱해둡니다.
참고로 쿼리 텍스트 자체를 기반으로 캐시 키를 생성합니다. 즉, 공백/조건이 다르면 별개 쿼리로 인식됩니다.
🛠️ 설정 방법 한눈에 보기
1. Query Cache 크기 설정
SET mysql-query_cache_size = 134217728; -- 128MB
2. 기본 TTL 설정 (초 단위)
SET mysql-query_cache_default_ttl = 60;
3. 특정 쿼리 패턴만 캐싱 (Query Rules)
SELECT count_star,sum_time,hostgroup,digest,digest_text FROM stats_mysql_query_digest_reset ORDER BY sum_time DESC;
+------------+-----------+-----------+--------------------+-------------------------------------------------------------------+
| count_star | sum_time | hostgroup | digest | digest_text |
+------------+-----------+-----------+--------------------+-------------------------------------------------------------------+
| 366300 | 508306254 | 1 | 0xE8930CB2CC9E68D7 | SELECT c from sbtest where id=? |
| 3663 | 6932505 | 1 | 0xB749413737FAF581 | SELECT DISTINCT c from sbtest where id between ? and ? order by c |
| 3663 | 6607248 | 1 | 0x78881FD58E5437B2 | SELECT c from sbtest where id between ? and ? order by c |
| 3663 | 5534740 | 1 | 0x547C0EAF9BC36E91 | SELECT SUM(K) from sbtest where id between ? and ? |
| 3663 | 5506153 | 1 | 0xDC1EE02F8CD8B09B | SELECT c from sbtest where id between ? and ? |
| 1 | 2372 | 1 | 0xD575B97BB01C8428 | SHOW TABLE STATUS LIKE ? |
+------------+-----------+-----------+--------------------+-------------------------------------------------------------------+
6 rows in set (0.00 sec)
INSERT INTO mysql_query_rules (rule_id,active,digest,cache_ttl,apply)
VALUES (5,1,'0xE8930CB2CC9E68D7',2000,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
📊 캐시 히트율 확인
캐시가 잘 작동하고 있는지 확인하는 방법도 필요하겠죠?
SELECT * FROM stats_mysql_query_cache;
- cache_hits: 캐시된 결과를 재사용한 횟수
- cache_misses: 캐시에 없어서 DB로 전달된 횟수
- cache_entries: 현재 캐시되어 있는 항목 수
캐시 히트율은 다음 공식으로 계산합니다:
Hit Rate = (cache_hits / (cache_hits + cache_misses)) * 100
⚠️ 주의할 점
- 캐시 대상 선정이 핵심입니다. 잦은 변경이 발생하는 테이블의 쿼리를 캐싱하면, 오래된 데이터를 반환할 가능성이 있습니다.
- Prepared Statement는 기본적으로 캐싱되지 않으니, ORM 사용 시는 주의가 필요합니다.
- 캐시 TTL은 짧으면 효과가 없고, 길면 데이터 일관성 문제가 생길 수 있습니다. 적절한 균형 조정이 필수입니다.
🧠 실제로 써보니
ProxySQL Query Cache는 단순한 구조지만 강력합니다. 대규모 트래픽의 읽기 부하를 효율적으로 줄이고, 빠른 응답을 가능하게 해줍니다.
하지만 만능은 아닙니다. 비정형 쿼리가 많거나, ORM이 동적으로 생성한 쿼리가 반복적으로 달라지는 환경에서는 히트율이 낮을 수 있습니다.
개인적인 팁이라면, 인기 카테고리 리스트, 제품 상세정보, 지역 정보 등 변경이 적고 트래픽이 집중되는 SELECT 쿼리에 캐시를 적용하는 것이 좋습니다.
📌 마무리
ProxySQL의 Query Caching은 설정이 단순하면서도 효과가 뛰어난 기능입니다. 특히 읽기 비중이 높은 서비스에서 DB 부하를 줄이기 위한 1차적인 대응책으로 추천드립니다.
DB 성능 튜닝과 쿼리 리팩터링 전에, ProxySQL 레이어에서 해결할 수 있는 부분을 먼저 검토해보는 것도 실무적인 접근이라고 생각합니다.