在 MySQL 中缓存

All lectures for ZH purposes
第 1 级 , 课程 880
可用

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_blocksQcache_free_blocksQcache_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调优可以将数据库性能提高数倍。这不仅可以加快应用程序的速度,还可以应对繁重的负载。

评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION