Mysql查询高速缓存区

时间:2022-12-23 21:54:42

  为了提高查询速度,Mysql会维护一个内存区域(官方文档指出,大小至少41984B)对查询结果进行缓存,当查询时发现缓存区里有数据则直接返回结果而不用去执行sql语句。

查询命中的条件

  每个缓存查询至少需要两个块(一个块用于查询文本,一个或多个块用于查询结果)。并且,每一个查询使用的每个表需要一个块。但是,如果两个或多个查询使用相同的表,仅需要分配一个块。

  对于两个查询语句是否相同的判定,Mysql是比较严格,查询必须是完全相同的(逐字节相同)才能够被认为是相同的。另外,同样的查询字符串由于其它原因可能认为是不同的。使用不同的数据库、不同的协议版本或者不同 默认字符集的查询被认为是不同的查询并且分别进行缓存。例如,以下两个查询是不相同的:

SELECT * FROM tbl_name
Select * from tbl_name

缓冲区配置

  在Mysql中,设置缓冲区大小命令为:

 mysql>SET GLOBAL query_cache_size = 41984;

  如果设置的query_cache_size小于41984,则会设置失败,并自动把它置为0。如果设置为0则表示不使用缓冲区。

  当query_cache_size大于0的情况下,并不能保证缓冲区会被使用,还必须根据变量query_cache_type来决定,该变量有3中状态,分别代表3中不同缓冲方式:

  • 0或OFF--------将阻止缓存或查询缓存结果。
  • 1或ON---------将允许缓存,以SELECT SQL_NO_CACHE开始的查询语句除外。
  • 2或DEMAND--------仅对以SELECT SQL_CACHE开始的那些查询语句启用缓存。

  设置方式如下:

mysql> SET SESSION query_cache_type = OFF;

  

查询结果的内存大小分配  

  要控制可以被缓存的具体查询结果的最大值,应设置query_cache_limit变量。 默认值是1MB。

当一个查询结果(返回给客户端的数据)从查询缓冲中提取期间,它在查询缓存中排序。因此,数据通常不在大的数据块中处理。查询缓存根据数据排序要求分配数据块,因此,当一个数据块用完后分配一个新的数据块。因为内存分配操作是昂贵的(费时的),所以通过query_cache_min_res_unit系统变量给查询缓存分配最小值。当查询执行时,最新的结果数据块根据实际数据大小来确定,因此可以释放不使用的内存。根据你的服务器执行查询的类型,你会发现调整query_cache_min_res_unit变量的值是有用的:

  • query_cache_min_res_unit默认值是4KB。这应该适合大部分情况。
  • 如果你有大量返回小结果数据的查询,默认数据块大小可能会导致内存碎片,显示为大量空闲内存块。由于缺少内存,内存碎片会强制查询缓存从缓存内存中修整(删除)查询。这时,你应该减少query_cache_min_res_unit变量的值。空闲块和由于修整而移出的查询的数量通过Qcache_free_blocks和Qcache_lowmem_prunes变量的值给出。
  • 如果大量查询返回大结果(检查 Qcache_total_blocks和Qcache_queries_in_cache状态变量),你可以通过增加query_cache_min_res_unit变量的值来提高性能。但是,注意不要使它变得太大。

  也就是说,则给查询结果分配缓冲区大小时,并不是再等待查询结果返回后根据结果大小来分配空间,而是先根据query_cache_min_res_unit分配一个内存,待结果返回后直接放入内存中。这时候分3种情况考虑:

  1. 如果(查询结果的大小=query_cache_min_res_unit),则直接把结果存入到该缓冲区中。
  2. 如果(查询结果的大小<query_cache_min_res_unit),则直接把结果存入到该缓冲区中,然后把多分配的空间释放掉,这种情况容易产生内存碎片。
  3. 如果(查询结果的大小>query_cache_min_res_unit),则需要再分配内存空间来存放结果

查询高速缓冲状态和维护

  可以使用下面的语句检查MySQL服务器是否提供查询缓存功能:

mysql> SHOW VARIABLES LIKE 'have_query_cache';

+------------------+-------+

| Variable_name    | Value |

+------------------+-------+

| have_query_cache | YES   |

+------------------+-------+

可以使用FLUSH QUERY CACHE语句来清理查询缓存碎片以提高内存使用性能。该语句不从缓存中移出任何查询。

RESET QUERY CACHE语句从查询缓存中移出所有查询。FLUSH TABLES语句也执行同样的工作。

为了监视查询缓存性能,使用SHOW STATUS查看缓存状态变量:

mysql> SHOW STATUS LIKE 'Qcache%';
+-------------------------+--------+
|变量名                   |值 |
+-------------------------+--------+
| Qcache_free_blocks      | 36     |
| Qcache_free_memory      | 138488 |
| Qcache_hits             | 79570  |
| Qcache_inserts          | 27087  |
| Qcache_lowmem_prunes    | 3114   |
| Qcache_not_cached       | 22989  |
| Qcache_queries_in_cache | 415    |
| Qcache_total_blocks     | 912    |
+-------------------------+--------+

清除缓冲区释放空间
  查询缓存使用长度可变块,因此Qcache_total_blocks和Qcache_free_blocks可以显示查询缓存内存碎片。执行FLUSH QUERY CACHE后,只保留一个空闲块。
mysql>FLUSH QUERY CACHE;

内存置换策略

查询缓冲区使用最近最少使用(LRU)策略来确定哪些查询从缓冲区中移出(根据Qcache_lowmem_prunes状态变量提供的信息能够帮助你你调整查询缓存的大小。它计算为了缓存新的查询而从查询缓冲区中移出到*内存中的查询的数目