上一节我们说到 Myql通信就像踢足球一样,发了请求之后只能等待命令执行完成才能重新掌握主动权。这一节我们主要说下,Mysql为了更快的返回结果做了什么?
QueryCache
在解析一个查询语句之前,如果查询缓存是打开的,Mysql会优先解析这个查询是否命中查询缓存中的数据。这个查找主要是通过一个对大小写敏感的Hash查找,如果查询与缓存中的查询有一个字节的不同都无法命中。
当查询命中缓存,Mysql会立即返回结果,跳过解析、优化、执行阶段。(这当然是最快的,不过当查询的表数据发生变化时,是无法命中的)。
如何判断命中
缓存存放在一个引用表中,通过Hash值引用,这个Hash包含了:查询本身、当前查找的数据库、客户端协议的版本等信息。 当判断缓存是否命中时,Mysql直接使用SQL语句和客户端发来的原始信息,所以任何字符的不同(如空格、注释等)都会导致缓存的不命中。
除此之外,当查询包括不确定的数据时,如Now()或者Current_Date()查询结果时不会缓存的。其实这也很容易理解,因为Now()函数的值一直变化,所以实际查询的SQL也会一直发生变化,所以时无法缓存的。事实上包含任何用户的自定义函数、存储过程、用户变量等都不会缓存(不会缓存的真多)
其实总结一句话就是:查询结果包含任何不确定的函数,那么查询缓存中是不可能找到结果的。需要注意的是,判断缓存是否命中是发生在SQL解析之前的事情,所以在执行查询缓存之前,Mysql是不知道SQL是否有变化函数的。
所以这就涉及到一个优化的点便是:
datediff(current_date,interval 1 day) 不会cache,
datediff(‘2016-07-11’,interval 1 day) 是会被cache的
(前提是query_cache已经打开)
凡事皆有利弊,提高查询速度本身便会带来一些其他的开销。
QueryCache的消耗
1、查询之前必须判断是否有缓存
2、假设一个可以缓存的SQL执行完成之后,Mysql发现这些数据没有被缓存,其将结果存入查询缓存中,这部分会带来一部分开销
3、对写也有一定的影响,因为当数据库中表写入数据时,Mysql需要将对应表的缓存标志失效。当查询缓存较大时或者随便较多时,会引起很大的内存消耗。特别是当缓存使用了很大的内存,缓存的失效可能会导致系统Hang住。
并且当使用InnoDB时,事务的一些特性会限制查询缓存的使用。当事务中某个语句修改某个表时,这个表的缓存会被设置失效。所以长时间的事务会降低查询缓存的命中率,因为这个表的所有查询都不会缓存:)
说了这么多QueryCache 到底是什么原理呢?内存是怎么分配的呢?如何正确的使用可以带来最大的性能提升呢,让我们下一章来扒一扒。
上一节我们说到 Myql通信就像踢足球一样,发了请求之后只能等待命令执行完成才能重新掌握主动权。这一节我们主要说下,Mysql为了更快的返回结果做了什么?
QueryCache
在解析一个查询语句之前,如果查询缓存是打开的,Mysql会优先解析这个查询是否命中查询缓存中的数据。这个查找主要是通过一个对大小写敏感的Hash查找,如果查询与缓存中的查询有一个字节的不同都无法命中。
当查询命中缓存,Mysql会立即返回结果,跳过解析、优化、执行阶段。(这当然是最快的,不过当查询的表数据发生变化时,是无法命中的)。
如何判断命中
缓存存放在一个引用表中,通过Hash值引用,这个Hash包含了:查询本身、当前查找的数据库、客户端协议的版本等信息。 当判断缓存是否命中时,Mysql直接使用SQL语句和客户端发来的原始信息,所以任何字符的不同(如空格、注释等)都会导致缓存的不命中。
除此之外,当查询包括不确定的数据时,如Now()或者Current_Date()查询结果时不会缓存的。其实这也很容易理解,因为Now()函数的值一直变化,所以实际查询的SQL也会一直发生变化,所以时无法缓存的。事实上包含任何用户的自定义函数、存储过程、用户变量等都不会缓存(不会缓存的真多)
其实总结一句话就是:查询结果包含任何不确定的函数,那么查询缓存中是不可能找到结果的。需要注意的是,判断缓存是否命中是发生在SQL解析之前的事情,所以在执行查询缓存之前,Mysql是不知道SQL是否有变化函数的。
所以这就涉及到一个优化的点便是:
datediff(current_date,interval 1 day) 不会cache,
datediff(‘2016-07-11’,interval 1 day) 是会被cache的
(前提是query_cache已经打开)
凡事皆有利弊,提高查询速度本身便会带来一些其他的开销。
QueryCache的消耗
1、查询之前必须判断是否有缓存
2、假设一个可以缓存的SQL执行完成之后,Mysql发现这些数据没有被缓存,其将结果存入查询缓存中,这部分会带来一部分开销
3、对写也有一定的影响,因为当数据库中表写入数据时,Mysql需要将对应表的缓存标志失效。当查询缓存较大时或者随便较多时,会引起很大的内存消耗。特别是当缓存使用了很大的内存,缓存的失效可能会导致系统Hang住。
并且当使用InnoDB时,事务的一些特性会限制查询缓存的使用。当事务中某个语句修改某个表时,这个表的缓存会被设置失效。所以长时间的事务会降低查询缓存的命中率,因为这个表的所有查询都不会缓存:)
说了这么多QueryCache 到底是什么原理呢?内存是怎么分配的呢?如何正确的使用可以带来最大的性能提升呢,让我们下一章来扒一扒。
To be continue…