쿼리 캐시는 매우 유용한 기능이지만 너무 많은주의를 기울이고 너무 크게 만들려는 유혹을받지 마십시오. 내부의 일부를 이해하면 아마도 그 점에서 도움이 될 것입니다.
쿼리 캐시는 사용 가능한 메모리의 하나의 큰 연속 청크로 시작합니다. 그런 다음 "블록"이이 큰 블록에서 조각됩니다.
- 캐시 된 각 쿼리는 블록을 사용합니다
- 동반자 결과 집합이 차단됩니다
- 캐시 된 쿼리에서 참조하는 각 테이블 (캐시에 해당 테이블을 참조하는 쿼리 수에 관계없이)도 테이블 당 하나씩 블록을 사용합니다.
블록 크기는 동적이지만 서버 query_cache_min_res_unit
는 블록 당 최소 바이트를 할당 하며 일반적인 기본값은 4096 바이트입니다.
기본 테이블이 변경되거나 새로운 쿼리를위한 공간을 확보하기 위해 제거 (prune)함으로써 쿼리, 관련 결과 및 테이블 참조가 캐시에서 제거 될 때마다 새로운 홀의 크기는 커지지 만 블록 크기는 크지 만 "사용 가능한 블록"의 수는 일반적으로 증가합니다. 두 개 이상의 연속 블록이 해제되면 "사용 가능한 블록"의 수는 1 씩만 증가하고 "사용 가능한 블록"은 새로 증가하면 전혀 증가하지 않습니다. 해제 된 블록은 이미 사용 가능한 블록과 인접합니다. 사용 가능한 블록의 크기가 커집니다. 쿼리 캐시에서 사용 가능한 열린 메모리 블록은 1 개의 사용 가능한 블록으로 계산됩니다.
물론, 무료 블록보다 작은 프리 블록 query_cache_min_res_unit
은 전혀 사용되지 않습니다.
따라서 쿼리 캐시 조각입니다. 서버가 새로운 쿼리를 캐시하고 충분한 크기의 여유 블록을 배열 할 수없는 경우 (기본 알고리즘이 복잡하기 때문에 설명이 간단합니다) 그 밖의 무언가를 정리해야합니다 Qcache_lowmem_prunes
. 정리할 대상을 결정하는 "최근에 사용 된"(LRU) 알고리즘이 있습니다.
서버가 왜 메모리를 조각 모음하지 않는지 물어 보는 것이 합리적 일 것입니다. 쿼리 캐시는 가능할 때 도움이되지만 전혀 전략적이지는 않습니다. 불필요한 유지 관리 작업으로 처리 시간 (특히 전역 잠금에 소요 된 시간)을 투자하고 싶지 않습니다.
캐시 된 결과가 지속적으로 변경되고 캐시의 전체 지점이 성능을 향상시키기 때문에 서버가 쿼리 캐시에서 메모리를 다시 정리 (조각 모음)하는 데 시간이 오래 걸리는 것은 비생산적입니다.
전역 잠금은 지나치게 큰 쿼리 캐시를 사용하지 않으려는 매우 좋은 이유입니다. 서버는 쿼리가 캐시되어 발생하는지 확인하고 성능이 저하 될 때까지 차례를 기다리는 동안 서버에서 너무 많은 시간을 소비합니다. .
그러나 이는 qcache_free_blocks
본질적으로 자유 공간 조각화의 지표입니다. 이제 쿼리 캐시에 사용 가능한 메모리의 비 연속 블록이 많이 있습니다. 캐시에 새 쿼리를 삽입하려면 쿼리, 결과 및 (때로는) 테이블 참조를 포함 할 수있는 충분한 여유 공간이 있어야합니다. 그렇지 않다면 다른 것이 있어야합니다 ... 이것은 당신이보고있는 것입니다. 가용 공간이 항상 연속적 일 필요는 없지만 (소스 코드를 읽음으로써 알 수있는 것부터) 조각화가있을 때 모든 구멍이 채워지는 것은 아닙니다.
그러나 조각화는 주어진 워크로드에 대해 시간이 지남에 따라 평준화되는 경향이 있습니다. 일반적으로 예상 한 시간 동안 쿼리 캐시에 아무것도 남아 있지 않기 때문입니다.
이는 어떤 식 으로든 쿼리 캐시가 단순하기 때문에 훌륭하기 때문입니다.
캐시 된 쿼리에서 참조하는 테이블의 데이터가 변경 될 때마다 변경 사항이 캐시 된 결과에 영향을 미치지 않더라도 해당 테이블과 관련된 모든 쿼리가 캐시에서 제거됩니다. 롤백 된 InnoDB 트랜잭션의 경우처럼 테이블이 변경되지만 변경되지 않는 경우에도 마찬가지입니다. 해당 테이블을 참조하는 쿼리 캐시 항목이 이미 제거되었습니다.
또한 서버가 실제로 쿼리를 구문 분석 하기 전에 들어오는 각 쿼리에 대해 쿼리 캐시를 확인 합니다. 일치하는 유일한 것은 정확히 바이트 단위의 다른 쿼리입니다. SELECT * FROM my_table
및 select * from my_table
쿼리 캐시가 실현되지 않도록 그들은 같은 쿼리있어, 바이트 단위 동일하지 않다.
FLUSH QUERY CACHE
쿼리 캐시를 비우지 않습니다. 쿼리 캐시를 조각 모음하므로 Qcache_free_blocks
"1"이됩니다. 여유 공간이 모두 통합되었습니다.
RESET QUERY CACHE
실제로 쿼리 캐시를 플러시합니다 (모든 내용을 지 웁니다).
FLUSH STATUS
카운터를 지 웁니다. 그러나의 대부분의 상태 변수를 0으로 만들기 때문에 일상적으로 수행하려는 작업이 아닙니다 SHOW STATUS
.
다음은 몇 가지 간단한 데모입니다.
기준선 :
mysql> show status like '%qcache%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67091120 |
| Qcache_hits | 0 |
| Qcache_inserts | 0 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 1 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+----------+
검색어 실행 ...
mysql> select * from junk where id = 2;
캐시의 총 블록 수는 1이고 총 블록 수는 3 개, 삽입 수는 1 개 증가했습니다.
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67089584 |
| Qcache_inserts | 1 |
| Qcache_queries_in_cache | 1 |
| Qcache_total_blocks | 4 |
+-------------------------+----------+
동일한 쿼리를 실행하지만 대문자를 다르게 사용하십시오.
mysql> SELECT * FROM junk where id = 2;
이 쿼리는 별도로 캐시되었습니다. 테이블에 이미 블록이 할당되어 있기 때문에 총 블록 수는 2 만 증가했습니다.
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67088560 |
| Qcache_inserts | 2 |
| Qcache_queries_in_cache | 2 |
| Qcache_total_blocks | 6 |
+-------------------------+----------+
이제 테이블에서 다른 행을 변경 합니다.
mysql> update junk set things = 'items' where id = 1;
쿼리와 테이블 참조는 캐시에서 무효화되어 1 개의 연속 사용 가능한 블록, 사용 가능한 모든 캐시 메모리 및 사용 가능한 모든 공간이 하나의 블록으로 통합됩니다.
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 1 |
| Qcache_free_memory | 67091120 |
| Qcache_queries_in_cache | 0 |
| Qcache_total_blocks | 1 |
+-------------------------+----------+
MySQL은 결정적이지 않은 캐시 (예 : SELECT NOW();
캐시하지 말라고하는 쿼리)에 쿼리를 저장하지 않습니다. SELECT SQL_NO_CACHE ...
결과를 캐시에 저장하지 않도록 서버에 지시하는 지시문입니다. 캐시가 후속 실행에 대해 믿을 수 없을 정도로 빠른 응답을 제공 할 때 쿼리의 실제 실행 시간을 벤치마킹하는 데 유용합니다.