mysql 的查询缓存是在完整的 select 语句基础上判断的,而且只是在刚收到 SQL 语句的时候才检查,所以子查询和存储过程都没办法使用查询缓存。
如果查询语句中包含任何的不确定因素或者函数,那么就不会命中查询缓存,不确定因素指客户端协议的版本等,而不确定函数指 now() 这种函数,它随着时间变化而变化,是不确定的。
在一个事务提交之前表的相关查询是不走缓存的。
打个比喻就是 mysql 将你的整个 sql 语句原封不动地先检查是否有不确定函数,如果有不确定函数就不走缓存,如果没有不确定函数,那么将 sql 语句做个 md5 计算,如果找得到计算的值就走缓存,否则就不走缓存。
为了用上查询缓存,优化的思路有下面这些:
1. 将子查询或者联结拆开成单表的查询,因为整个 sql 语句只要有不确定的函数就不走缓存,拆开后其中的某些查询可能就走缓存了。
2. 将不确定函数替换成确定的值,比如你用系统函数 current_date() 生成的日期就可以用提前计算好的日期替换掉。