原因如下:
1.QC命中率低,因为需要请求sql和请求时的环境(连接的数据库、协议版本、字符集等)与缓存中的一模一样才会命中缓存
2.由于QC需要缓存最新的数据,所以在数据发生变化时(比如增删改操作)QC就会刷新,这导致缓存会频繁的写入、擦除,消耗过多资源
此外,QC也不适用于下面几个场景:
读取mysql的系统表
子查询或者外层查询
查询语句中用到随机函数,或者now这种函数,给查询结果带来不确定性(每次查询结果会有差异),
查询中用到了视图,临时表
存储过程,触发器中调用的sql也不适合
查询语句加了SQL_NO_CACHE
查询语句未引用任何表
类似select into这种sql,显示加锁的sql都不会去缓存
更奇葩的是查询语句命中缓存之后,会接着验证用户的访问权限,如果无权也会使用QC
最为重要的是,在MySQL里QC是由一个全局锁在控制,每次更新QC的内存块都需要进行锁定。
例如,一次查询结果是20KB,当前 query_cache_min_res_unit 值设置为 4KB(默认值就是4KB,可调整),那么么本次查询结果共需要分为5次写入QC,每次都要锁定,可见其成本有多高。
所以QC适合表数据量少,更新频率低,查询比较多,比如配置表、权限表。
关闭方法很简单,有两种:
1、同时设置选项 query_cache_type = 0 和 query_cache_size = 0;
2、如果用源码编译MySQL的话,编译时增加参数 --without-query-cache 即可;