Mysql 为什么即使有一半的查询缓存未被使用,我仍会收到lowmen修剪的通知?

Mysql 为什么即使有一半的查询缓存未被使用,我仍会收到lowmen修剪的通知?,mysql,sql,caching,Mysql,Sql,Caching,我使用的是一个监控系统,每隔几个小时就会报告有很多lowmem修剪 2013年12月5日星期四01:21:52 UTC 7347查询缓存lowmem在600秒内修剪(12.24/秒) 2013年12月5日星期四10:21:52 UTC 10596查询缓存lowmem在600秒内修剪(17.66/秒) 2013年12月5日星期四11:26:52 UTC 8979查询缓存lowmem在600秒内修剪(14.96/秒) 我的16MB查询缓存中约6MB未被使用 mysql> SHOW VARIAB

我使用的是一个监控系统,每隔几个小时就会报告有很多lowmem修剪

2013年12月5日星期四01:21:52 UTC 7347查询缓存lowmem在600秒内修剪(12.24/秒)

2013年12月5日星期四10:21:52 UTC 10596查询缓存lowmem在600秒内修剪(17.66/秒)

2013年12月5日星期四11:26:52 UTC 8979查询缓存lowmem在600秒内修剪(14.96/秒)

我的16MB查询缓存中约6MB未被使用

mysql> SHOW VARIABLES LIKE 'query_cache_size';
+------------------+----------+
| Variable_name    | Value    |
+------------------+----------+
| query_cache_size | 16777216 |
+------------------+----------+
1 row in set (0.00 sec)
为什么在缓存未填满的情况下删除查询

我应该增加还是减少缓存大小

其他信息

mysql> FLUSH STATUS;
30分钟后

mysql> SHOW STATUS LIKE '%Qcache%';
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| Qcache_free_blocks      | 1935    |
| Qcache_free_memory      | 5154904 |
| Qcache_hits             | 43918   |
| Qcache_inserts          | 33074   |
| Qcache_lowmem_prunes    | 4443    |
| Qcache_not_cached       | 10438   |
| Qcache_queries_in_cache | 6276    |
| Qcache_total_blocks     | 14713   |
+-------------------------+---------+
8 rows in set (0.00 sec)

当任何INSERT/UPDATE/DELETE语句修改关联表中的数据时,查询缓存将使条目过期。这不会等待缓存填满

说:

如果表发生更改,则使用该表的所有缓存查询都将无效并从缓存中删除。这包括使用映射到已更改表的合并表的查询。表可以由多种类型的语句更改,例如INSERT、UPDATE、DELETE、TRUNCATE table、ALTER table、DROP table或DROP DATABASE


你的问题是:


如果使用InnoDB并且插入在表的末尾,查询缓存是否会使条目过期

是的,没错。例如,假设查询缓存项与mytable中的查询相关联。如果在
mytable
的末尾插入,则此查询的缓存结果将无效

查询缓存在决定数据的给定更改是否影响缓存项方面没有太多的智能。它假设如果您更改了表中的任何内容,则必须放弃缓存中以任何方式与该表关联的所有查询

只有当缓存结果在插入后发生变化时,它才能应用更多的智能来丢弃某些查询结果。但它会怎么做呢?它必须在插入后再次运行查询,将结果与存储在缓存中的结果进行比较。如果它们不同,则替换缓存中的结果

但它必须对缓存中的每个查询结果都这样做。请注意,状态输出显示查询缓存中有5638个查询。当然,并不是所有这些都与您插入的同一个表相关联,但我们可以假设它们中的许多都是相关联的

一次插入导致数百或数千条SELECT语句被重新执行以刷新其缓存结果,这不是一个好的折衷办法

因此,折衷的做法是,对表的更改会清除与该表相关联的所有缓存结果,即使这不是严格必要的


因此,查询缓存不是缓存查询的非常精确的方法。它对某些工作负载很有帮助,例如,如果您的应用程序倾向于重复给定的查询多次,而表没有收到任何更改。但是,在许多情况下,工作负载使查询缓存没有帮助,在某些情况下,维护查询缓存的开销实际上对性能有害


如果您想要更精确的缓存机制,您必须在应用程序中自己编写,将某些结果保存到memcached或类似的快速内存缓存中。然后,您就有责任跟踪数据更改时需要刷新哪些条目。

如果使用InnoDB并且插入在表的末尾,查询缓存是否会使条目过期?
mysql> SHOW STATUS LIKE '%Qcache%';
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| Qcache_free_blocks      | 1935    |
| Qcache_free_memory      | 5154904 |
| Qcache_hits             | 43918   |
| Qcache_inserts          | 33074   |
| Qcache_lowmem_prunes    | 4443    |
| Qcache_not_cached       | 10438   |
| Qcache_queries_in_cache | 6276    |
| Qcache_total_blocks     | 14713   |
+-------------------------+---------+
8 rows in set (0.00 sec)