The MySQL Query Cache
The query cache does not work in an environment where you have multiple mysqld servers updating the sameMyISAM
tables.
The query cache is used for prepared statements under the conditions described in Section 8.10.3.1, “How the Query Cache Operates”.
As of MySQL 5.6.5, the query cache is not supported for partitioned tables, and is automatically disabled for queries involving partitioned tables. The query cache cannot be enabled for such queries. (Bug #53775)
query_cache_size
system variable to 0. By disabling the query cache code, there is no noticeable overhead.
(mysql@localhost) [(none)]> select @@query_cache_size; --查看query cache大小
+--------------------+
| @@query_cache_size |
+--------------------+
| 1048576 |
+--------------------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> select @@query_cache_type; --查看query cache是否开启
+--------------------+
| @@query_cache_type |
+--------------------+
| OFF |
+--------------------+
1 row in set (0.00 sec)
SQL_NO_CACHE
option 组织语句进入query cache(以为进入后,一修改,就又会被flush out)
How the Query Cache Operates
SELECT * FROMtbl_name
Select * fromtbl_name
- queries 是一个子查询
- queries在函数,触发器或event中执行
com_select 变量记录的是无缓存的查询次数+错误查询+权限检查查询。
(mysql@localhost) [(none)]> show global status like 'Com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 6 |
+---------------+-------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> select count(*) from fan.ab
-> ;
ERROR 1146 (42S02): Table 'fan.ab' doesn't exist
(mysql@localhost) [(none)]> show global status like 'Com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 7 |
+---------------+-------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> show global status like 'Com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 3 |
+---------------+-------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> show global status like 'Qcache_hits';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Qcache_hits | 0 |
+---------------+-------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> select * from fandb.ab;
+----+------+
| id | name |
+----+------+
| 5 | 5s |
| 6 | 6s |
| 7 | 7s |
| 8 | 8s |
| 9 | 9s |
+----+------+
5 rows in set (0.00 sec)
(mysql@localhost) [(none)]> show global status like 'Com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 4 |
+---------------+-------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> show global status like 'Qcache_hits';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Qcache_hits | 0 |
+---------------+-------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> select * from fandb.ab;
+----+------+
| id | name |
+----+------+
| 5 | 5s |
| 6 | 6s |
| 7 | 7s |
| 8 | 8s |
| 9 | 9s |
+----+------+
5 rows in set (0.00 sec)
(mysql@localhost) [(none)]> show global status like 'Com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 4 |
+---------------+-------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> show global status like 'Qcache_hits';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Qcache_hits | 1 |
+---------------+-------+
1 row in set (0.00 sec)
MERGE
tables that map to the changed table。表会因下面的statements产生变化:
INSERT
,
UPDATE
,
DELETE
,
TRUNCATE TABLE
,
ALTER TABLE
,
DROP TABLE
, or
DROP DATABASE
.
InnoDB
tables.
SELECT SQL_CALC_FOUND_ROWS ...
queries and stores a value that is returned by a following
SELECT FOUND_ROWS()
query.
FOUND_ROWS()
returns the correct value even if the preceding query was fetched from the cache because the number of found rows is also stored in the cache. The
SELECT FOUND_ROWS()
query itself cannot be cached.
(mysql@localhost) [(none)]> SELECT SQL_CALC_FOUND_ROWS * FROM fandb.ab limit 1;
+----+------+
| id | name |
+----+------+
| 5 | 5s |
+----+------+
1 row in set (0.00 sec)
(mysql@localhost) [(none)]> select found_rows();
+--------------+
| found_rows() |
+--------------+
| 5 |
+--------------+
1 row in set (0.00 sec)
A query also is not cached under these conditions:
-
It refers to user-defined functions (UDFs) or stored functions.
-
It refers to user variables or local stored program variables.
-
It refers to tables in the
mysql
,INFORMATION_SCHEMA
, orperformance_schema
database. -
(MySQL 5.6.5 and later:) It refers to any partitioned tables.
-
It is of any of the following forms:
SELECT ... LOCK IN SHARE MODE SELECT ... FOR UPDATE SELECT ... INTO OUTFILE ... SELECT ... INTO DUMPFILE ... SELECT * FROM ... WHERE autoincrement_col IS NULL
The last form is not cached because it is used as the ODBC workaround for obtaining the last insert ID value. See the Connector/ODBC section of Chapter 23, Connectors and APIs.
Statements within transactions that use
SERIALIZABLE
isolation level also cannot be cached because they useLOCK IN SHARE MODE
locking. -
It uses
TEMPORARY
tables. -
It does not use any tables.
-
It generates warnings.
-
The user has a column-level privilege for any of the involved tables.
Two query cache-related options may be specified in SELECT
statements:
-
The query result is cached if it is cacheable and the value of the
query_cache_type
system variable isON
orDEMAND
. -
SQL_NO_CACHE
The server does not use the query cache. It neither checks the query cache to see whether the result is already cached, nor does it cache the query result. (Due to a limitation in the parser, a space character must precede and follow the
SQL_NO_CACHE
keyword; a nonspace such as a newline causes the server to check the query cache to see whether the result is already cached.)
Examples:
SELECT SQL_CACHE id, name FROM customer; SELECT SQL_NO_CACHE id, name FROM customer;
The have_query_cache
server system variable indicates whether the query cache is available:
mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| have_query_cache | YES |
+------------------+-------+
When using a standard MySQL binary, this value is always YES
, even if query caching is disabled.
Several other system variables control query cache operation. These can be set in an option file or on the command line when starting mysqld. The query cache system variables all have names that begin withquery_cache_
. They are described briefly in Section 5.1.4, “Server System Variables”, with additional configuration information given here.
To set the size of the query cache, set the query_cache_size
system variable. Setting it to 0 disables the query cache, as does setting query_cache_type=0
. By default, the query cache is disabled. This is achieved using a default size of 1M, with a default for query_cache_type
of 0. (Before MySQL 5.6.8, the default size is 0, with a default query_cache_type
of 1.)
To reduce overhead significantly, also start the server with query_cache_type=0
if you will not be using the query cache.
当你将query_cache_size设为非零值,要注意最小值为40K,用以存储其自身结构。 (The exact size depends on system architecture.)
mysql>SET GLOBAL query_cache_size = 40000;
Query OK, 0 rows affected, 1 warning (0.00 sec) mysql>SHOW WARNINGS\G
*************************** 1. row *************************** Level: Warning Code: 1282 Message: Query cache failed to set size 39936; new query cache size is 0 mysql>SET GLOBAL query_cache_size = 41984;
Query OK, 0 rows affected (0.00 sec) mysql>SHOW VARIABLES LIKE 'query_cache_size';
+------------------+-------+ | Variable_name | Value | +------------------+-------+ | query_cache_size | 41984 | +------------------+-------+
如何确认一个系统的 Query Cache 的运行是否健康,命中率如何,设置量是否足够?
MySQL 提供了一系列的 Global Status 来记录 Query Cache 的当前状态,具体如下:
Qcache_free_blocks:目前还处于空闲状态的 Query Cache 中内存 Block 数目
Qcache_free_memory:目前还处于空闲状态的 Query Cache 内存总量
Qcache_hits:Query Cache 命中次数
Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,也就是没有命中的次数
Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要从中删除老的 Query Cache 以给新的 Cache 对象使用的次数
Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL
Qcache_queries_in_cache:目前在 Query Cache 中的 SQL 数量
Qcache_total_blocks:Query Cache 中总的 Block 数量
可以根据这几个状态计算出 Cache 命中率,计算出 Query Cache 大小设置是否足够,总的来说,我个人不建议将 Query Cache 的大小设置超过256MB,这也是业界比较常用的做法。
Query Cache 命中率= Qcache_hits / ( Qcache_hits + Qcache_inserts );
来源: <http://jackyrong.iteye.com/blog/2173523>