热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

高性能MySql进化论(十三):查询缓存机制

对于很多的数据库系统都能够缓存执行计划,对于完全相同的sql,可以使用已经已经存在的执行计划,从而跳过解析和生成执行计划的过程。MYSQL以及Oracle提供了更为高级的查询结果缓存功能,对于完全相同的SQL(字符串完全相同且大小写敏感)可以执行返回查询结

对于很多的数据库系统都能够缓存执行计划,对于完全相同的sql, 可以使用已经已经存在的执行计划,从而跳过解析和生成执行计划的过程。MYSQL以及Oracle提供了更为高级的查询结果缓存功能,对于完全相同的SQL (字符串完全相同且大小写敏感) 可以执行返回查询结

对于很多的数据库系统都能够缓存执行计划,对于完全相同的sql, 可以使用已经已经存在的执行计划,从而跳过解析和生成执行计划的过程。MYSQL以及Oracle提供了更为高级的查询结果缓存功能,对于完全相同的SQL (字符串完全相同且大小写敏感) 可以执行返回查询结果。本文主要介绍MYSQL 查询缓存的一些特性,Oracle query cache可以参考http://www.oracle.com/technetwork/articles/sql/11g-caching-pooling-088320.html

如果你有一个不经常改变的表并且服务器收到该表的大量相同查询,查询缓存在这样的应用环境中十分有用。对于许多Web服务器来说存在这种典型情况,它根据数据库内容生成大量的动态页面。

1 查询缓存的工作机制

Mysql 判断是否命中缓存的办法很简单,首先会将要缓存的结果放在引用表中,然后使用查询语句,数据库名称,客户端协议的版本等因素算出一个hash值,这个hash值与引用表中的结果相关联。如果在执行查询时,根据一些相关的条件算出的hash值能与引用表中的数据相关联,则表示查询命中

通过have_query_cache服务器系统变量指示查询缓存是否可用:

mysql> SHOW VARIABLES LIKE 'have_query_cache';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| have_query_cache | YES   |
+------------------+-------+

为了监视查询缓存性能,使用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    |
+-------------------------+--------+

1.1 查询缓存机制失效的场景

先不论查询缓存机制有利有弊,先看看哪些场景下会导致缓存机制失效

1. 如果查询语句中包含一些不确定因素时(例如包含 函数Current()),该查询不会被缓存,不确定因素主要包含以下情况

· 引用了一些返回值不确定的函数

BENCHMARK()

CONNECTION_ID()

CURDATE()

CURRENT_DATE()

CURRENT_TIME()

CURRENT_TIMESTAMP()

CURTIME()

DATABASE()

带一个参数的ENCRYPT()

FOUND_ROWS()

GET_LOCK()

LAST_INSERT_ID()

LOAD_FILE()

MASTER_POS_WAIT()

NOW()

RAND()

RELEASE_LOCK()

SYSDATE()

不带参数的UNIX_TIMESTAMP()

USER()

· 引用自定义函数(UDFs)。

· 引用自定义变量。

· 引用mysql系统数据库中的表。

· 下面方式中的任何一种:

SELECT ...IN SHARE MODE

SELECT ...FOR UPDATE

SELECT ...INTO OUTFILE ...

SELECT ...INTO DUMPFILE ...

SELECT * FROM ...WHERE autoincrement_col IS NULL

· 被作为编写好的语句,即使没有使用占位符。例如,下面使用的查询:

char *my_sql_stmt = "SELECT a,b FROM table_c";
   /* ...*/
mysql_stmt_prepare(stmt,my_sql_stmt,strlen(my_sql_stmt));

不被缓存。

· 使用TEMPORARY表。

· 不使用任何表。

· 用户有某个表的列级别权限。

1.2 额外的消耗

如果使用查询缓存,在进行读写操作时会带来额外的资源消耗,消耗主要体现在以下几个方面

· 查询的时候会检查是否命中缓存,这个消耗相对较小

· 如果没有命中查询缓存,MYSQL会判断该查询是否可以被缓存,而且系统中还没有对应的缓存,则会将其结果写入查询缓存

· 如果一个表被更改了,那么使用那个表的所有缓冲查询将不再有效,并且从缓冲区中移出。这包括那些映射到改变了的表的使用MERGE表的查询。一个表可以被许多类型的语句更改,例如INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE。

对于InnoDB而言,事物的一些特性还会限制查询缓存的使用。当在事物A中修改了B表时,因为在事物提交之前,对B表的修改对其他的事物而言是不可见的。为了保证缓存结果的正确性,InnoDB采取的措施让所有涉及到该B表的查询在事物A提交之前是不可缓存的。如果A事物长时间运行,会严重影响查询缓存的命中率

查询缓存的空间不要设置的太大。

因为查询缓存是靠一个全局锁操作保护的,如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况

1.3 配置参数

MYSQL提供了一些参数来控制查询缓存的行为,参数如下

· query_cache_limit

MYSQL能够缓存的最大查询结果,查询结果大于该值时不会被缓存。默认值是1048576(1MB)

如果某个查询的结果超出了这个值,Qcache_not_cached的值会加1,如果某个操作总是超出可以考虑在SQL中加上SQL_NO_CACHE来避免额外的消耗

· query_cache_min_res_unit

查询缓存分配的最小块的大小(字节)。 默认值是4096(4KB)。

· query_cache_size

为缓存查询结果分配的内存的数量,单位是字节,且数值必须是1024的整数倍。默认值是0,即禁用查询缓存。请注意即使query_cache_type设置为0也将分配此数量的内存。

· query_cache_type

设置查询缓存类型。设置GLOBAL值可以设置后面的所有客户端连接的类型。客户端可以设置SESSION值以影响他们自己对查询缓存的使用。下面的表显示了可能的值:

选项

描述

0或OFF

不要缓存或查询结果。请注意这样不会取消分配的查询缓存区。要想取消,你应将query_cache_size设置为0。

1或ON

缓存除了以SELECT SQL_NO_CACHE开头的所有查询结果。

2或DEMAND

只缓存以SELECT SQL_NO_CACHE开头的查询结果。

该变量默认设为ON。

· query_cache_wlock_invalidate

一般情况,当客户端对MyISAM表进行WRITE锁定时,如果查询结果位于查询缓存中,则其它客户端未被锁定,可以对该表进行查询。将该变量设置为1,则可以对表进行WRITE锁定,使查询缓存内所有对该表进行的查询变得非法。这样当锁定生效时,可以强制其它试图访问表的客户端来等待。

2 查询缓存的优化流程

当开启了查询缓存的功能后,可以通过一些参数以及状态值来观察查询缓存的使用情况。

流程以及涉及到的参数参见下图


3 查询缓存的优化

除了上图提到的一些优化策略外,还可以通过下面的措施来提高查询缓存的效率

· 尽量用小表的简单替代大表的复杂查询

· 尽量用批量写入取代单条写入

· 控制query_cache_size的大小,甚至是禁用查询缓存

· 通过DEMAND+SQL_CACHE/SQL_NO_CACHE来灵活控制某个select是否需要进行缓存

· 对于写密集型的应用,直接禁用查询缓存

4 Reference

更多信息可以参考:http://dev.mysql.com/doc/refman/5.1/zh/database-administration.html#query-cache


推荐阅读
  • 1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ... [详细]
  • PHP 5.2.5 安装与配置指南
    本文详细介绍了 PHP 5.2.5 的安装和配置步骤,帮助开发者解决常见的环境配置问题,特别是上传图片时遇到的错误。通过本教程,您可以顺利搭建并优化 PHP 运行环境。 ... [详细]
  • 深入理解 SQL 视图、存储过程与事务
    本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ... [详细]
  • 本文深入探讨 MyBatis 中动态 SQL 的使用方法,包括 if/where、trim 自定义字符串截取规则、choose 分支选择、封装查询和修改条件的 where/set 标签、批量处理的 foreach 标签以及内置参数和 bind 的用法。 ... [详细]
  • 本文详细介绍了如何通过多种编程语言(如PHP、JSP)实现网站与MySQL数据库的连接,包括创建数据库、表的基本操作,以及数据的读取和写入方法。 ... [详细]
  • 本文详细介绍了IBM DB2数据库在大型应用系统中的应用,强调其卓越的可扩展性和多环境支持能力。文章深入分析了DB2在数据利用性、完整性、安全性和恢复性方面的优势,并提供了优化建议以提升其在不同规模应用程序中的表现。 ... [详细]
  • 本周信息安全小组主要进行了CTF竞赛相关技能的学习,包括HTML和CSS的基础知识、逆向工程的初步探索以及整数溢出漏洞的学习。此外,还掌握了Linux命令行操作及互联网工作原理的基本概念。 ... [详细]
  • 深入理解Cookie与Session会话管理
    本文详细介绍了如何通过HTTP响应和请求处理浏览器的Cookie信息,以及如何创建、设置和管理Cookie。同时探讨了会话跟踪技术中的Session机制,解释其原理及应用场景。 ... [详细]
  • 解决PHP与MySQL连接时出现500错误的方法
    本文详细探讨了当使用PHP连接MySQL数据库时遇到500内部服务器错误的多种解决方案,提供了详尽的操作步骤和专业建议。无论是初学者还是有经验的开发者,都能从中受益。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 360SRC安全应急响应:从漏洞提交到修复的全过程
    本文详细介绍了360SRC平台处理一起关键安全事件的过程,涵盖从漏洞提交、验证、排查到最终修复的各个环节。通过这一案例,展示了360在安全应急响应方面的专业能力和严谨态度。 ... [详细]
  • MySQL中枚举类型的所有可能值获取方法
    本文介绍了一种在MySQL数据库中查询枚举(ENUM)类型字段所有可能取值的方法,帮助开发者更好地理解和利用这一数据类型。 ... [详细]
  • 本文详细介绍了如何通过命令行启动MySQL服务,包括打开命令提示符窗口、进入MySQL的bin目录、输入正确的连接命令以及注意事项。文中还提供了更多相关命令的资源链接。 ... [详细]
  • 解读MySQL查询执行计划的详细指南
    本文旨在帮助开发者和数据库管理员深入了解如何解读MySQL查询执行计划。通过详细的解析,您将掌握优化查询性能的关键技巧,了解各种访问类型和额外信息的含义。 ... [详细]
  • 本文详细介绍了如何使用ActionScript 3.0 (AS3) 连接并操作MySQL数据库。通过具体的代码示例和步骤说明,帮助开发者理解并实现这一过程。 ... [详细]
author-avatar
LoveCherryz
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有