直到最近,我都将查询缓存视为提高查询性能的一个非常重要的工具。今天,我正在收听一个播客,其中讨论了将查询缓存调整为 0,并使用更好的内存缓存解决方案(例如 memcache.d)。
但他们也提到在少数情况下 query_cache 很有帮助。因此,一般建议是按需启用它(使用SELECT SQL_CACHE
, 和 query_cache_type = 2 配置设置)。
我的问题是,假设你有一个像 memcache.d 这样的缓存解决方案,什么类型的情况会使 query_cache 更优化?
编辑:添加链接
我认为那里有很多关于查询缓存的错误信息。
查询缓存的最佳情况是,当您必须检查大量行,但只将少数行返回给客户端时。这很常见的典型情况是没有应用适当优化或索引的系统。
在许多查询是主键查找的情况下,或者非常优化的情况下,查询缓存可能会导致负面的可伸缩性。是的:它让事情变得更糟!
这样做的原因是,该设计添加了一些内部锁定,这限制了您的 MySQL 服务器在多核机器上的扩展。
查询缓存是 MySQL 中许多“突然停止”的原因——并非所有这些都很明显。在 Percona Server 中,我们向进程列表添加了一个新状态(Waiting on Qcache mutex): http ://www.percona.com/docs/wiki/percona-server:features:status_wait_query_cache_mutex
(免责声明,我为 Percona 工作。)
Memcached(或Coherence)缓存整个结果集。数据库中的缓存缓存数据库行。因此,假设您有一个访问模式,其中查询是固定的并且数据不经常更改(例如
select * from restaurants where location='london'
)。每次添加新餐厅时,您可能会运行该查询数千次,因此缓存整个结果集是有意义的,它可以节省每次访问数据库的时间 - 但您仍然拥有 RDBMS 和 SQL 的所有可管理性和灵活性(您只需要在数据更改的奇怪情况下踢出缓存)。有人将此称为参考数据或静态数据。但是,假设您有一个 ad-hoc 访问模式(也许您的用户有很多选项可以准确地找到他们今晚想在哪里吃饭,但很少有两个用户具有完全相同的偏好)。然后,您可能想要缓存行(以保存到磁盘),但在内存中即时组装每个结果集。那时您会希望数据库本身管理它缓存的内容和方式。在大多数情况下,混合或分层方法效果最好。
请注意,还有第三种缓存在起作用——操作系统的文件系统缓存。我不喜欢这些,原因很简单,如果你从磁盘读取一个块,它现在存在于数据库缓存和文件系统缓存中,但数据库不“知道”后者,所以它不能用它做任何聪明的事情,比如看看它的使用频率。从 DBA 的角度来看,系统上任何多余的内存都超出了操作系统本身需要满足的条件,这都是浪费。
我不认为这里已经提到过,但是查询缓存也可能对性能产生不利影响;也许这就是您的播客中提到的内容。如果查询缓存效率很低
Qcache_hits / (Qcache_hits + Com_select)
(Qcache_lowmem_prunes/Uptime
Peter Zaitsev 的这篇文章更详细地介绍了一些事情。与这里的一些答案相反,他指出缓存是针对整个结果集的。但是,该职位已有数年历史。一些最近的想法是在四月发布的。
我一直觉得它缓存的是完整的结果集,而不是上面提到的行。如果您有完全相同的查询,它将跳过解析/计划并返回相同的结果集(其最大大小由 控制
query_cache_limit
)。如果您禁用了查询缓存,那么选择非常简单的高读取环境,则没有启用锁定机制。我最近在 MySQL 5.5 中使用多个缓冲池体验了这一点。
如果您重复调用相同的基本查询,则无需一遍又一遍地解析相同的查询,直到奶牛回家。在繁重的读取环境中,使用您知道将始终调用的一小部分 SELECT,一个小的查询缓存就足够了。
对于重读环境中的大量数据,memcached 更方便。查询缓存在这一点上是一只跛鸭。