概述MySQL查询缓存可以对数据库优化起到很大的作用。今天主要对这方面做一个总结。一起来看看吧~1.缓存条件,原理MySQL使用QueryCache来缓存我们执行的SELECT语句和语句的结果集,MySql在实现QueryCache的具体技术细节上类似于典型的KV存储,就是将SELECT语句和查询语句的结果集做一个HASH映射,保存在某个内存区域。当客户端发起SQL查询时,QueryCache的查找逻辑是先验证SQL对应的权限,然后使用QueryCache查找结果(注意一定要完全一样,即使有一个多余的空格或者大小写不同,都会被认为是不同的),即使使用相同的SQL,不同的字符集,不同的协议等也会被认为是不同的查询,分别缓存)。它不需要通过Optimizer模块对执行计划进行分析和优化,也不需要和任何存储引擎交互,减少了大量的磁盘IO和CPU操作,所以有时候效率很高。查询缓存的工作流程如下:1:命中条件缓存存在于一个哈希表中,通过查询SQL、查询数据库、客户端协议等作为key,在判断是否命中之前,MySQL不会解析SQL,而是直接使用SQL去查询缓存,SQL字符的任何差异,比如空格,注释,都会导致缓存不命中。如果查询中有不确定的数据,比如CURRENT_DATE()和NOW()函数,查询完成后不会缓存。所以,包含不确定数据的查询肯定找不到可用的缓存2:工作流服务器收到SQL,以SQL和其他一些条件为key查找缓存表(额外的性能消耗)如果找到缓存,则直接返回缓存(性能提升)如果没有找到缓存,则执行SQL查询,包括对原始SQL的解析、优化等,执行SQL查询结果后,将SQL查询结果存入缓存表(额外的性能消耗)2、相关SQL语句2.1、查看SQLCache参数:showvariableslike'%query_cache%';各参数含义如下:Qcache_free_blocks:缓存中相邻内存块的数量。大数字表示可能存在碎片。FLUSHQUERYCACHE会对缓存进行碎片整理以获得空闲块。Qcache_free_memory:缓存中的空闲内存。Qcache_hits:每次查询命中缓存时增加Qcache_inserts:每次插入查询时增加。命中数除以插入数就是未命中率。Qcache_lowmem_prunes:缓存内存不足且必须清理以便为更多查询腾出空间的次数。这个数字最好在很长一段时间内查看;如果数字在增长,则可能是严重碎片化或内存不足的迹象。(上面的free_blocks和free_memory可以告诉你是哪种情况)Qcache_not_cached:不适合缓存的查询数,通常是因为这些查询不是SELECT语句或者使用了now()等函数。Qcache_queries_in_cache:当前缓存的查询(和响应)数量。Qcache_total_blocks:缓存中的块数。2.2.打开SQL缓存:setglobalquery_cache_type=1;2.3.关闭SQL缓存:setglobalquery_cache_type=0;2.4.设置缓存空间:设置全局query_cache_size=1024*1024*64(64M)2.5。固定SQL语句语句不适用缓存:selectsql_no_cache*fromtablename注意:如果SQL语句的大小写发生变化或者数据表中的数据发生变化,则不会调用缓存。2.6.配置查询缓存vi/etc/my.cnfquery_cache_size=300Mquery_cache_type=13.mysql的清除缓存FLUSH语法(clearcache)FLUSHflush_option[,flush_option]如果要清除MySQL使用的一些内部缓存,应该使用FLUSH命令。为了执行FLUSH,你必须有reload权限。flush_option可以是以下任何一项:HOSTS这是最常用和经常遇到的。主要用于清除主机缓存表。如果您的一些主机更改了IP号码,或者如果您收到错误消息Host...isblocked,您应该清空主机表。当连接到MySQL服务器时,给定主机连续发生超过max_connect_errors的错误,出于安全原因,MySQL将阻止来自主机的进一步连接请求。清除主机表允许主机再次尝试连接。LOGS关闭当前二进制日志文件并创建一个新的二进制日志文件,新二进制日志文件的名称将当前二进制日志文件的编号增加1。权限这也经常使用。每当重新授权时,为了以防万一新的授权立即生效,一般都会执行。目的是将数据库授权表中的授权重新加载到缓存中。TABLES关闭所有打开的表,此操作将清除查询缓存的内容。FLUSHTABLESWITHREADLOCK关闭所有打开的表,同时给数据库中的所有表加上读锁,直到显式执行解锁表。该操作常用于数据备份。STATUS将大部分状态变量重置为0。MASTER删除二进制日志索引文件中的所有二进制日志文件,将二进制日志文件的索引文件重置为空,并创建一个新的二进制日志文件,但不再推荐和这样做更改为重置主机。你可以想象,我曾经是一团糟。本来一个简单的命令就可以完成,但是需要好几个命令。以前的方法是先找出当前的二进制日志文件名,然后使用purge进行操作。QUERYCACHE重组查询缓存,消除碎片,提高性能,但不影响查询缓存中已有的数据,这一点不同于Flushtable和ResetQueryCache(会清除查询缓存的内容)。SLAVE类似于resetreplication,让从库忘记主库的复制位置,同时也删除下载的relaylog。和Master一样,不再推荐,改为ResetSlave。这也很有用。一般来说,Flush操作会记录在二进制日志文件中,但是FLUSHLOGS、FLUSHMASTER、FLUSHSLAVE、FLUSHTABLESWITHREADLOCK是不会记录的,所以如果将以上操作记录在二进制日志文件中,就会造成从库损坏。影响。注意:Reset操作实际上起到了增强版Flush操作的作用。4、缓存的内存管理缓存会在内存中开辟一块内存(query_cache_size)来维护缓存数据,其中大约40K的空间用来维护缓存的元数据,比如空间内存,数据表的映射以及查询结果、SQL和查询结果的映射等。MySQL将这个大内存块分成小内存块(query_cache_min_res_unit),每个小块存储自己的类型、大小和查询结果数据,以及指向前面和后面的指针返回内存块。MySQL需要设置单个小存储块的大小,在SQL查询开始的时候申请一个空间(结果还没有得到),所以即使你的缓存数据没有达到这个大小,也需要使用这个大小的数据块来存储(这一点和Linux文件系统的块是一样的)。如果结果超过了这个内存块的大小,就需要再申请一个内存块。当查询完成,发现请求的内存块有空闲时,会释放空闲空间,这会造成内存碎片问题,查询缓存存储查询结果后,查询剩余的查询碎片见下图。这里query1和query2之间的空白部分是内存碎片。这部分空闲内存在查询1完成查询后释放。假设这个空间的大小小于MySQL设置的内存块大小,就不能再使用,造成碎片问题。在查询开始时申请内存块分配需要锁定整个空闲内存区域,因此分配内存块会消耗大量资源。注意这里所说的分配内存是在MySQL初始化时开辟的那块内存上分配的。五、何时使用缓存&性能测量开启缓存是否能提高系统性能是一个比较难的话题1、从缓存命中率来看,缓存命中率=缓存命中(Qcache_hits)/查询次数(Com_select)2.从缓存写入率来看,写入率=缓存写入次数(Qcache_inserts)/查询次数(Qcache_inserts)3.从命中写入率来看,Ratio=命中次数(Qcache_hits)/写入次数(Qcache_inserts),称为一个能够反映高性能MySQL性能提升的指标。一般来说,如果达到3:1,就认为querycache有效,最好达到10:1,不能过分,尤其是一些写入频繁的系统,启用QueryCache功能可能不会提高系统性能,有时会降低。原因是为了保证QueryCache缓存的内容与实际数据绝对一致,当数据表发生更新、删除或插入操作时,MySql会强制使所有引用该表的查询SQL失效。对于密集的写操作,启用查询缓存很可能会导致频繁的缓存失效,间接造成内存激增和CPU激增,这对本就非常繁忙的数据库系统来说是一个巨大的负担。6.查询缓存问题分析及配置总结缓冲池分析。
