7.1 DB端缓存
MySQL 在处理表时使用高度可扩展的算法,因此即使使用少量内存也可以运行 MySQL。当然,为了获得更好的性能,您需要更多的 RAM。
要查看当前设置,请连接到数据库
#mysq -u root -p
mysql> show variables like 'query_cache%';
+------------------------------+-----------+
| Variable_name | Value |
+------------------------------+-----------+
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 134217728 |
| query_cache_type | ON |
| query_cache_wlock_invalidate | OFF |
+------------------------------+-----------+
5 rows in set (0.00 sec)
首先,确保缓存已启用。多变的:
query_cache_type
必须为 ON (1) 或 DEMAND (2)query_cache_limit
- 确定将进入缓存的结果的最大大小query_cache_size
不同于零。使用 DEMAND 时,只有包含该指令的请求才会被缓存SQL_CACHE;
query_cache_min_res_unit
用于存储缓存查询结果的已分配内存块的最小大小。MySQL 不会将缓存存储在一大块内存中,而是根据需要分配最小大小query_cache_min_res_unit
(默认为 4KB)的块。最后一个这样的块被截断为数据大小,剩余的内存被释放。
缓存的作用是,当服务器收到一个请求时,它会查看请求的哈希值是否在缓存中。如果哈希匹配 - 服务器立即返回结果 - 无需解析请求、优化等。开销——伴随着缓存机制——浏览缓存、将查询结果写入缓存等。
如果缓存中有很多小请求,那么这可能会由于大量空闲块而导致内存碎片。而这又会导致缓存条目因内存不足而被删除。在这种情况下,降低 的值是有意义的query_cache_min_res_unit
。如果您的大多数查询产生大量结果,则增加此设置可以提高性能。
让我们尝试评估一下效果。我们看看缓存命中计数器如何变化(Qcahe_hits),由于内存不足而声明无效的请求数(Qcache_lowmem_prunes),SELECT类型的请求总数(并且只有它们被缓存):
#mysq -u root -p
mysql> show status like 'Qcache%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Qcache_free_blocks | 715 |
| Qcache_free_memory | 130369640 |
| Qcache_hits | 24209 |
| Qcache_inserts | 16215 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 444 |
| Qcache_queries_in_cache | 1740 |
| Qcache_total_blocks | 4225 |
+-------------------------+-----------+
8 rows in set (0.00 sec)
7.2 当前缓存状态
要监视查询缓存,请使用SHOW STATUS
:
mysql> SHOW STATUS LIKE 'Qcache_%';
+-------------------------+----------+
| Variable_name | Value |
+-------------------------+----------+
| Qcache_free_blocks | 10 |
| Qcache_free_memory | 16755496 |
| Qcache_hits | 49812 |
| Qcache_inserts | 103999 |
| Qcache_lowmem_prunes | 0 |
| Qcache_not_cached | 180 |
| Qcache_queries_in_cache | 6 |
| Qcache_total_blocks | 28 |
+-------------------------+----------+
8 rows in set (0.00 sec)
Qcache_free_blocks
显示缓存中有多少空闲块(将随着缓存请求的增加而减少);Qcache_total_blocks
——占用块数;Qcache_free_memory
- 显示用于缓存的免费“可用”内存;Qcache_hits
- 请求的数量,其结果是从缓存中获取的,没有实际访问数据库;Qcache_inserts
- 添加到缓存中的请求数;Qcache_lowmem_prunes
- 由于内存不足而从缓存中删除的请求数;Qcache_not_cached
- 由于使用时间管理功能等而未写入缓存的请求数;Qcache_queries_in_cache
- 缓存中的请求数。
您可以查看 SELECT 查询的总数:
mysql> show status like 'Com_select';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_select | 16719 |
+---------------+-------+
1 row in set (0.00 sec)
7.3 缓存效率
“建议通过除以变量的值来评估缓存的有效性Qcache_hits on Qcache_hits + Com_select
,因为在处理请求时,Qcache_hits 计数器会增加(如果请求是从缓存中处理的)或 Com_select(如果请求未被缓存)。这个方法在O'reilly的《Mysql性能优化》中有推荐
网上还有一个方法
qcache_hit_ratio = qcache_hits / (qcache_hits + qcache_inserts + qcache_not_cached)
如果这个值 > 0.8,那么 80% 的请求都被缓存了,这是一个很好的指标。
如果%
缓存命中率低,则需要增加该值 query_cache_size
。
当前值可以这样查看:
SHOW VARIABLES LIKE 'query_cache_size';
问题又来了:如何选择合适的值query_cache_size?
这会有所帮助Qcache_lowmem_prunes
。该变量存储由于需要缓存新请求而从缓存中删除的请求数。有必要争取这样的缓存大小,Qcache_lowmem_prunes
它只会稍微增加。为此,建议比较Qcache_lowmem_prunes
每小时值的差异和mysql在同一小时内收到的请求数。
“在实践中,可以使用 2 个公式之一来计算 query_cache_size:
query_cache_size = (number of requests for 10 minutes)*(average response volume on request) * 1,2
或者
query_cache_size = (number of requests for 10 minutes)*(average response volume on request) * 1,2
query_cache_size = (10分钟内的流量) * 1.2 "
这将缓存请求 10 分钟 + 额外提供 20% 的内存用于缓存碎片和额外的缓存预留
您可以分别使用Bytes_sent变量计算对请求的响应数量和平均音量
所以query_cache_size
我们增加了价值,之后你应该注意价值Qcache_total_blocks
,Qcache_free_blocks
和Qcache_queries_in_cache
。MySQL 以块的形式存储缓存。对于 1 个请求,需要 2 个块:一个用于请求文本本身,第二个用于结果。
如果我们从值考虑表Qcache%
缓存块总数Qcache_total_blocks – 28
现在缓存了请求 6,这意味着 6 * 2 = 12 个块正忙
免费块Qcache_free_blocks – 10
。空闲越多Qcache_free_blocks
,缓存的“碎片化”程度就越大。
如果大多数查询的结果数据量很小,那么有必要减小最小缓存块大小query_cache_min_res_unit
,默认情况下为 4 KB。
如果大多数请求返回大量数据,则值得增加缓存块的大小。
最主要的是要达到一个最小值Qcache_free_blocks
。
如果计数器Qcache_not_cached
很大,您可以尝试增加变量query_cache_limit
——这将允许您增加限制并缓存“不适合”的查询结果。
以下配置变量负责使用查询缓存:
query_cache_size
— 查询缓存的大小。query_cache_size = 0
禁用缓存使用;query_cache_limit
- 缓存中存储的最大样本的大小;query_cache_wlock_invalidate
- 确定如果数据所属的表被锁定以供读取,是否将从缓存中取出数据。 =
要启用 mysql 查询缓存,只需将以下行添加到my.cnf([mysqld] 节):
query_cache_size = 268435456
query_cache_type =1
query_cache_limit =1 048576
并重启服务。
7.4 不使用缓存的地方
未缓存:
- 来自的请求
SQL_NO_CACHE
- 准备好的查询
(Prepared statements);
- 作为外部查询的子查询的查询;
- 在存储过程和函数中查询;
- 使用函数的查询:
BENCHMARK ()
,CONNECTION_ID ()
,CONVERT_TZ ()
,CURDATE ()
,CURRENT_DATE ()
,CURRENT_TIME ()
,CURRENT_TIMESTAMP ()
,CURTIME ()
,DATABASE ()
,ENCRYPT ()
有一个参数,FOUND_ROWS ()
,GET_LOCK ()
,LAST_INSERT_ID ()
,LOAD_FILE ()
,MASTER_POS_WAIT ()
,NOW ()
,RAND ()
,RELEASE_LOCK ()
,SLEEP ()
,SYSDATE ()
,UNIX_TIMESTAMP ()
没有参数,USER ()
,UUID ();
- 在mysql系统数据库或INFORMATION_SCHEMA中使用存储函数、用户变量或引用表进行查询;
- • 以下形式的请求:
SELECT ... IN SHARE MODE
SELECT ... FOR UPDATE
SELECT ... INTO OUTFILE ...
SELECT ... INTO DUMPFILE ...
SELECT * FROM ... WHERE autoincrement_col IS NULL
- 使用临时表或根本不使用表的查询;
- 请求产生警告(warnings);
您可以使用以下命令对缓存进行碎片整理:
mysql>flush query cache;
清除 - 命令:
mysql>flush query cache;
最重要的
从不使用默认设置在生产中工作. 这将导致服务器的大部分资源未被使用。适当的MySQL调优可以将数据库性能提高数倍。这不仅可以加快应用程序的速度,还可以应对繁重的负载。
GO TO FULL VERSION