MYSQL缓存查询原理和优缺点

视频地址:MYSQL缓存查询原理和优缺点_哔哩哔哩_bilibili

一 缓存查询过程

【缓存查询过程】

【查询缓存是否开启】

have_query_cache

作用:显示服务器是否支持查询缓存。

返回值:

YES:表示服务器支持查询缓存。

NO:表示服务器不支持查询缓存。

注意事项:

MySQL 8.0 及以上版本:从 MySQL 8.0 开始,查询缓存功能已被移除,因此 have_query_cache 将始终返回 NO。

MySQL 5.7 及更早版本:在这些版本中,查询缓存仍然可用,但默认是关闭的。

query_cache_limit

作用:限制单个查询结果可以占用的最大缓存空间。

单位:字节。

默认值:1MB。

范围:1 到 query_cache_size。

query_cache_min_res_unit

作用:设置分配给每个缓存块的最小内存单元大小。

单位:字节。

默认值:4KB。

范围:4KB 到 1MB。

query_cache_size

作用:设置查询缓存所占用的最大内存大小。

单位:字节。

默认值:在 MySQL 5.7 中默认为 0MB(禁用),在更早版本中默认为 4MB。

范围:0 到 1GB。

query_cache_type

作用:控制是否启用查询缓存。

可选值:

OFF:完全禁用查询缓存。

ON:开启查询缓存,所有非唯一查询都将被缓存。

DEMAND(默认值):只有通过 SQL_CACHE 显式标记的查询才会被缓存。

query_cache_wlock_invalidate

作用:控制写锁是否使缓存失效。

可选值:

0:写锁不会使缓存失效。

1(默认值):写锁会使缓存失效。

【缓存统计参数查看】

Qcache_free_blocks

描述:查询缓存中空闲块的数量。

用途:反映查询缓存内部可用空间的情况,有助于理解缓存的空间利用率。

Qcache_free_memory

描述:查询缓存中剩余的自由内存数量(以字节为单位)。

用途:表示查询缓存还有多少可用空间,可用于新的查询结果的存储。

Qcache_hits

描述:查询缓存命中的次数。

用途:衡量查询缓存的有效性,即有多少次查询可以直接从缓存中获取结果而不需要重新执行。

Qcache_inserts

描述:查询结果插入到缓存中的次数。

用途:表示有多少次查询的结果被添加到了查询缓存中。

Qcache_lowmem_prunes

描述:由于内存不足而从缓存中删除的查询结果的数量。

用途:当查询缓存内存不足时,系统会自动删除部分缓存条目来释放空间。这个计数器反映了这种行为发生的频率。

Qcache_not_cached

描述:无法被缓存的查询数量(例如包含 SQL_NO_CACHE 的查询)。

用途:帮助理解为什么某些查询没有被缓存。

Qcache_queries_in_cache

描述:当前在缓存中的查询数量。

用途:反映查询缓存中存储了多少个不同的查询结果。

Qcache_total_blocks

Qcache_total_blocks

描述:查询缓存中总块的数量。

用途:表示查询缓存的物理存储结构的规模。

【开启缓存】

my.ini配置

[mysqld]

query_cache_type = 1

query_cache_size = 1M

二 缓存优缺点

【优点】

        1、减少磁盘I/O操作:由于Query Cache是基于内存的缓存机制,可以直接从内存中获取查询结果,避免了频繁访问磁盘以获取数据,从而显著降低了磁盘I/O操作的需求。

        2、减轻CPU计算负担:Query Cache能够在权限验证后立即尝试从缓存中返回结果,这意味着许多查询不需要经过优化器的分析和优化过程,也不需要与存储引擎进行交互,这大大减少了CPU的计算工作量。

【缺点】

  1. 哈希值索引的局限性MySQL使用一个类似于 HashMap 的数据结构来存储查询缓存,通过一个哈希值索引来定位缓存项。这个哈希值由查询本身、当前查询的数据库、客户端协议、版本号等信息计算得出。这意味着即使是微小的变化(如空格、注释等)也会导致不同的哈希值,从而无法命中缓存。
  2. 查询字符串严格匹配:在判断是否命中缓存之前,MySQL不会解析SQL语句。它直接使用原始的SQL字符串来查找缓存,这意味着即使查询逻辑相同,只要字符串中有任何字符不同(包括空格、注释等),都会导致缓存命中失败。
  3. 不支持特定类型的查询:如果查询SQL中包含任何用户自定义函数、存储函数、用户变量、临时表或者MySQL库中的系统表,其查询结果都不会被缓存。例如,包含 LIKENOW()CURRENT_DATE() 等函数的查询将不会被缓存。
  4. prepared statement的限制:在MySQL 5.1之前的版本中,使用预编译语句 (prepared statement) 的查询结果永远不会被缓存,即使参数完全相同也不会命中缓存。虽然在5.1版本后有所改进,但在实际应用中仍然可能存在限制。
  5. 结果集大小限制:如果查询返回的结果集太大(超过 query_cache_limit 配置的值),则不会被缓存。
  6. 分库分表环境下的无效性:在分库分表的环境下,MySQL查询缓存通常不起作用,因为查询可能跨多个分片执行,而缓存只能在单个数据库实例级别起作用。
  7. 触发器和自定义函数的影响:如果查询涉及到触发器或自定义函数,MySQL查询缓存也将失效。这是因为这些特性可能会改变数据状态,导致缓存数据过时。
  8. 日期和时间函数的优化建议:对于使用日期和时间函数的查询,如 CURRENT_DATE NOW 等,如果返回的是基于小时或天级别的数据,建议预先计算这些值并将其作为常量值传递到查询中,以提高缓存的命中率。
  9. 并发访问的共享特性:虽然查询缓存是通过sessions共享的,意味着一个客户端查询的缓存结果可以被其他客户端使用,但这可能导致数据一致性问题,特别是在高并发环境下。
  10. 缓存检查前置但不一定命中:每个查询语句在执行前都会先经过缓存检查,即便该查询最终无法命中缓存,这也增加了不必要的开销。
  11. 缓存存储带来的系统消耗:如果查询结果可以被缓存,那么在查询执行完成后,结果会被存储到缓存中,这一过程会带来额外的系统资源消耗。
  12. 写操作导致的缓存失效开销:当表中的数据发生变化时(例如通过 INSERT, UPDATE, DELETE 等操作),MySQL 必须清除与该表相关的所有缓存条目,如果缓存很大或存在大量碎片,这一过程可能导致显著的性能下降。
  13. 大缓存下的更新延迟:如果 query_cache 设置得非常大,并且该表的查询模式非常多变,那么查询缓存的失效速度较慢,因此即使是简单的 UPDATE 或 INSERT 操作也可能变得非常缓慢。
  14. 频繁的缓存失效:在表结构或数据发生改变时,如执行 INSERT, UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP DATABASE 等操作,查询缓存中的数据将不再有效,相应的缓存条目会被清空,这可能导致缓存的有效利用率较低。
  15. 空间消耗:缓存占用物理内存,如果缓存的数据集过大,则可能会消耗大量的内存资源。
  16. 不适合高写操作场景:在写操作频繁的环境中,由于每次写入都会导致缓存失效,因此查询缓存的有效性会迅速降低。
  17. 并发性能问题:在高并发环境下,频繁的缓存更新和失效可能导致性能瓶颈,尤其是在多核处理器上。
  18. 管理复杂度:正确配置和维护查询缓存需要较高的系统调优知识水平,以避免潜在的性能问题。
  19. 不支持所有查询类型:并非所有的查询都支持缓存,例如包含用户变量或某些函数的查询就不支持缓存。

在 MySQL 8.0 版本中,默认已经移除了查询缓存功能,因为它的维护成本高并且在很多情况下并不能显著提升性能

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值