작동 방식
- Query cache는 system-wide한 글로벌 메모리 공간
- Query cache는 Full scan등과 같이 큰 공간이 필요한 결과는 캐시하지 않도록
캐시 최대 사이즈를 제한(query_cache_limit) - Query의 결과를 캐시하기 위해서 메모리의 공간을 할당 받을 때,
query_cache_min_res_unit 단위로 할당 받으며 (필요시 더 추가적으로),
캐시 작업이 완료된 이후 남은 미사용 공간은 반납하게 된다. - Query cache는 테이블 단위로 Invalidate 되기 때문에,
테이블이 상당히 자주 변경된다면 cache의 효율이 떨어질 수 있다. - 일반적으로는 Query cache의 매치 기준은 Query 문장이 동일한지(대소문자 및 공백까지) 비교하는 방식이며 InnoDB의 경우에는 레코드 기반의 락을 사용하며 MVCC의 제어가 필요하기 때문에
재사용 가능한지 판단은 Query 문장뿐만 아니라 Transaction Id로 레코드 접근성까지 비교해야 함 - Query cache의 관리 비용은 얻는 효과에 비하면 아주 미미하지만,
가끔은 캐시 내용을 invalidate 하는데 상당히 많은 비용이 필요할 수도 있음 - 일반적으로 Query cache는 아래의 경우 상당히 도움이 된다.
- 테이블이 자주 변경되지 않는 경우
- 쿼리의 실행 과정은 복잡하고 많은 처리가 필요하지만 결과 셋의 사이즈가 작은 경우
- 동일 쿼리가 자주 실행되는 경우 - Query cache의 Hit-Ratio는 계산하는 MySQL의 Status 값 Key_reads를 Status값 Key_read_requests로 나누는 방법으로 계산하지만, 이 값이 90%면 좋고 20%면 나쁘다는 단순한 판단은 힘듬
-> Query cache의 효율성 판단은 실제 운영 시스템에서 활성화/비활성화를 비교해보는 것이 제일 좋을 듯 하지만, 운영 시스템이므로 주의가 필요
-> query_cache_size 설정 변수는 전역이면서 동적 변수이기 때문에 실시간으로 변경이 가능하므로 서비스 영향 없이 설정 변경 후 비교 가능
(주의해야 할 것은 기존과 동일하든지 다른 값이든지 일단 한번 설정이 되면 지금까지의 캐시된 내용은 모두 제거됨)
메모리 할당 방식
- 1) 그림의 아래 부분 처럼 각 색깔별로 A,B,C,D,E 쿼리들이 실행되어서, 1) 번과 같은 상태의 Query cache가 있다고 가정해보자
- 그림에서 하나의 영역은 Query cache block 으로 일반적으로 "query_cache_min_res_unit"로 정의된 사이즈이며,
- <1>번이라고 적힌 영역은 캐시될 ResultSet 을 저장하기 위해서 "query_cache_min_res_unit" 크기의 메모리 블럭을 할당 받아서 사용하다가 남는 공간은 다시 반납하게 되는데, 이 때문에 발생한 빈 공간임 (Fragmentation이라고도 하며, 이런 공간들은 쉽게 재활용되지 못함)
- 뒷 부분의 흰색 블럭들은 아직 미사용된 블럭들을 표시함 - 2) 이 상태에서 아래와 같이 tab2와 tab4를 변경하는 쿼리가 실행되면, 해당 테이블을 참조하는 모든 Query cache는 모두 제거됨
- UPDATE tab2 SET ... WHERE ...
- UPDATE tab4 SET ... WHERE ...
이런 공간들은 주위의 미사용 영역들과 병합되어서, 나중에 재활용될 수 있음
(이런 공간들도 모두 일반적으로 Fragmentation 이라고 표현함) - 3) 아래 명령을 이용하여 이렇게 발생한 Query cache의 Fragmentation을 제거하고,
미 사용 영역을 모두 연속된 공간으로 만들어줄 수 있음
- FLUSH QUERY CACHE;
이 명령은 Query cache 전체에 대해서 변경되지 않도록 락을 걸기 때문에 조심해서 실행해야 함 - 이러한 Query cache 의 block 할당에 관련된 정보는 MySQL의 상태값으로 확인 가능함
- Qcache_total_blocks : 무조건 할당된 공간까지의 모든 block들(사용중이든 아니든)의 수를 보여줌
- Qcache_free_blocks : 미사용 block들 (Fragmentation이라고 표현한 영역들)의 수를 보여줌
- 1)번 그림 : Qcache_total_blocks -> 16, Qcache_free_blocks -> 2
- 2)번 그림 : Qcache_total_blocks -> 16, Qcache_free_blocks -> 3
- 3)번 그림 : Qcache_total_blocks -> 11, Qcache_free_blocks -> 1
제약 사항
- 아래와 같은 형태로 실행되는 쿼리는 Query cache를 사용하지 못함
- PreparedStatement로 실행되는 쿼리 (MySQL 5.1.17 이후 부터는 Query cache를 사용 가능)
- Stored Procedure, Function, Trigger 내부에서 실행되는 쿼리
- Sub Query 형태로 실행되는 쿼리
관련 설정 변수
- query_cache_limit
이 값으로 설정된 사이즈 이상의 결과 셋을 가지는 경우에는 Query cache에 캐시하지 않도록 설정 - query_cache_min_res_unit
Query cache에서 결과 셋을 캐시하기 위한 메모리 공간을 할당 받을 때 사용하는 메모리 할당 최소 단위 사이즈 - query_cache_size
Query cache의 전체 사이즈를 설정하며 1024Byte의 배수로 설정,
Query cache를 완전히 비활성화하기 위해서는 이 변수의 값을 0으로 설정해야 한다. - query_cache_type
Query 의 결과 셋을 어떻게 저장할지를 결정함,
- OFF는 캐시하지 않음,
- ON은 SQL_NO_CACHE 힌트가 없는 SELECT 문장의 결과 셋은 캐시 대상으로 가정,
- DEMAND 는 SQL_CACHE 힌트가 SELECT 문장에 있는 결과 셋만 캐시 대상으로 가정 - query_cache_wlock_invalidate
어떤 Client가 MyISAM 테이블에 Write lock을 가지고 있는 경우,
다른 Client가 Query cache에서 결과를 가져갈 수 있는 SELECT문장을 실행하는 것은 Block되지 않는데, 이 값을 TRUE로 설정하면 결과를 Query cache에서 가져갈 수 있다 하더라도, 다른 Client는 대기해야 하도록 만든다.
출처 : http://intomysql.blogspot.com/
728x90
댓글