MySQL-查询结果缓存

摘要:
合理配置MySQL缓存以提高缓存命中率何时应用MySQL缓存对于一些不经常更改数据且具有大量相同SQL查询的表,I.应用程序系统何时从缓存中获取数据?此时,数据库直接使用缓存中的内容。可以看出,如果您想直接使用缓存中的数据,您在最近两次使用了相同的SQL语句(假设没有考虑其他条件),并且需要首次查询2010年的发货数据。使用的SQL语句与第一个查询完全相同。

  众所周知,系统读取数据时,从内存中读取要比从硬盘上速度要快好几百倍。故现在绝大部分应用系统,都会最大程度的使用缓存(内存中的一个存储区域),来提高系统的运行效率。MySQL数据库也不例外。在这里,笔者将结合自己的工作经验,跟大家探讨一下,MySQL数据库中缓存的管理技巧:如何合理配置MySQL数据库缓存,提高缓存命中率。

  合理配置MySQL缓存 提高缓存命中率

  什么时候适用MySQL缓存

    对于一些不常改变数据且有大量相同sql查询的表,查询缓存会节约很大的性能。

  一、什么时候应用系统会从缓存中获取数据?

  数据库从服务器上读取数据时,可以从硬盘的数据文件中获取数据,也可以从数据库缓存中读取数据。现在数据库管理员需要搞清楚的是,在什么样的情况下,系统是从缓存中读取数据,而不是从硬盘的数据文件中读取数据?

  简单的说,数据缓存就是内存中的一块存储区域,其存储了用户的SQL文本以及相关的查询结果。通常情况下,用户下次查询时,如果所使用的SQL文本是相同的,并且自从上次查询后,相关的纪录没有被更新过,此时数据库就直接采用缓存中的内容。从这个原则中,可以看到如果要直接使用缓存中的数据,至少要满足以下几个条件。

  一是所采用的SQL文本是相同的。当前后两次用户使用了相同的SQL语句(假设不考虑其他条件),则服务器会从缓存中读取结果,而不需要再去解析和执行SQL语句。这里需要注意的是,这里的SQL文本必须一次不差的完全相同。如果前后两次查询,使用了不同的查询条件。如第一次查询时没有输入Where条件语句。后来发现数据量过多,利用了Where条件了过滤查询的结果。此时即使最后的查询结果是相同的,系统仍然是从数据文件中获取数据,而不是从数据缓存中。再如,Select后面所使用的字段名称也必须是相同的。如果有一个字段名称不同或者前后两次查询所使用的字段数量不同,则系统都会认为是不同的SQL语句,而重新解析并查询。

  二是从数据缓存的角度考虑,大小写是不敏感的。如前后两次查询时,采用的字段名称可能只有大小写的差异。如第一次使用的是大小,第二次使用的是小写,这系统认为仍然是相同的SQL语句。或者说关键字大小写等等这都是不敏感的。

  三是要满足二次查询之间,数据记录包括表结构都没有被更改过。如果记录所在的标更改了,如增加了一个字段等等,此时使用这个表的所有缓冲数据系统将自动清空。这里需要注意,这里指的更改是一个广义的更改,包括表中任何数据或者结果的改变。举一个简单的例子,第一次查询时用户需要查询2010年的出货数据。查询后有用户在这个表中插入了一条2011年1月份的出货信息。然后又有用户需要查询2010年的出货信息。使用的SQL语句与第一次查询时完全相同。在这种情况下,数据库系统会使用缓存中的数据吗?答案是否定的。因为当中间用户插入一条记录时,系统会自动清空跟这个表相关的所有缓存记录。当第二次查询时,缓存中已经没有这张表对应的缓存信息。此时就需要重新解析并查询。

  四是需要注意,默认字符集对缓存命中率的影响。通常情况下,如果客户端与服务器之间所采用的默认字符集不同,则即使查询语句相同、在两次查询之间记录与表结构也没有被更改,系统仍然认为是不同的查询。对于这一点需要特别的注意,大家比较容易忽视。

  二、提高缓存命中率的建议。

  从上面的条件分析中可以看出,利用缓存中的数据具有比较严格的条件。其实这些条件也是合情合理的。主要是为了保障数据的一致性。对以上这些条件有深入的认识之后,现在数据库管理员需要考虑的是,如何来提高这个缓存的命中率?对此笔者有如下几个建议。

  一是在配置时,客户端与服务器端要使用相同的字符集。如果客户端(或者说第三方工具)与服务器端使用的字符集不同,那么任何情况下都不会使用缓存功能。特别在国内,需要用到中文的字符集。此时特别需要注意,客户端默认字符集要与服务器端的默认字符集相同。注意,这里是相同,而不是兼容。有时候即使采用了不同的字符集,客户端上仍然可以正常显示。这主要是因为有些字符集虽然不相同,但是是相互兼容的。在缓存管理上,需要相同,光兼容还不行。只要字符大小写、空格或者注释有一点点不同,查询缓存就认为这是一个不同的查询。
  二是在客户端上,要固化查询的语句。如现在有财务人员和采购人员同时从系统中查询11月份的出货数据。显然他们岗位职责不同,所需要字段的内容是不同的。此时在客户端出,可以允许用户设置自己所需要的表单格式。但是笔者建议,后台所采用的SQL语句最好是相同的。这里数据会经过三个渠道:后台数据库、客户端、用户。笔者的意识时,后台数据库与客户端之间的交互采用相同的SQL语句。然后客户端与用户之间进行交互时,根据用户定义的格式(包括字段前后的排列、不包括查询条件语句的差异)向用户显示数据。此时由于采用了相同的SQL语句(只是用户对于显示格式的要求不同),从而可以提高应用系统的查询效率。

  三是提高内存中缓存的配置,来提高命中率。一般在服务器启动时,操作系统会跟数据库软件协商缓存空间的大小。当缓存工作不足时,缓存中最旧的缓存记录会被最新的消息所覆盖。可见,如果能够提高缓存空间,就可以提高命中率。这就好像打靶,目标多了,命中的几率也会高许多。不过用户的并发数越多,这个设置的效果会越不明显。

  四是通过分区表可以提高缓存的命中率。在上面的条件分析中,大家可以看到,只要所查询的表中插入了一条记录,系统就会清空缓存记录。现在以查询出货记录为例。出货记录表每天都在更新,而用户在年初时,会经常需要查询上一年的出货记录。此时由于这个表中的数据每个小时都在更新,那么缓存中的信息会不断的被情况。此时缓存的命中率显然不会很高。针对这种情况,笔者建议可以采用分区表。如可以通过系统设置,将2010年的出货记录单独存放在一个出货的分区表中。即每一个年度都使用一张单独的分区表。此时2011年的纪录,就不会影响到2010年的分区表。此时如果用户重复查询2010年的出货信息,只要其使用的SQL语句相同(没有采用不同的查询条件),那么就可以享受缓存机制所带来的效益,提高应用系统的查询效果。。

  三、多个应用对缓存的影响。

  通常情况下,MySQL数据库的缓存是根据服务器内存的大小自动分配的。如果一台服务器上只有一个MySQL应用,那么固然最好。不过在实际工作中,为了降低信息化投资的成本,往往会在同一台服务器上布置多个信息化应用。由于其他信息化应用也需要使用内存的空间作为缓存,那么MySQL数据库中缓存空间就可能变小。如果遇到这种情况下,数据库管理员需要跟系统工程师进行协商,为各种不同的应用根据性能要求的不同,手工设置不同的缓存空间。如此的话,就可以避免同一台服务器上不同信息化应用对缓存的冲突。

  配置和适用查询缓存的方法:

    开启: 在my.ini中配置query_cache_type(0[off], 1[on], 2[demand]; 0不使用; 1默认使用缓存, 如果查询语句用SELECT SQL_NO_CACHE ...开头则不缓存; 2默认不使用缓存, 如果查询语句使用SELECT SQL_CACHE开头则使用缓存)

    查看配置: show variables like '%cache%';

      have_query_cache: 为YES表示缓存开启

      query_cache_type: on表示默认使用缓存

      query_cache_limit: 能缓存的单条查询结果容量最大值, 超过此值则不会缓存

      query_cache_size: 查询缓存总共占内存空间大小, 一般设置为256M为一个不错的大小

    查询缓存状态: show stats like 'Qcache%';

      Qcache_free_blocks: 查询缓存中空闲的block数目

      Qcache_free_memory: 空闲的内存总量

      Qcache_cache_hits: 命中的次数

      Qcache_cache_inserts: 向缓存中插入新的缓存结果的次数(也就是没有命中的次数)

      Qcache_lowmem_prunes: 当 Query Cache内存容量不够,需要从中删除老的单条查询结果以给新的查询结果对象使用的次数

      Qcache_not_cached: 没有被缓存的SQL数, 包括无法被缓存的SQL以及由于query_cache_type设置的不会被缓存的SQL

      Qcache_queries_in_cache: 目前在内存中的SQL数量

      Qcache_total_blocks: 内存中总的Block数量

免责声明:文章转载自《MySQL-查询结果缓存》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Module.modules()和Module.children()Vue(三)-- class与style绑定、条件渲染、列表渲染、列表的搜索和排序下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

代码注入漏洞

代码注入 维基百科,自由的百科全书     跳到导航跳到搜索 代码注入(Code injection)是一种肇因于处理非法数据的计算机臭虫应用。代码注入可被攻击者用来导入代码到某特定的计算机程序,以改变程序的运行进程或目的。代码注入攻击的结果可以是灾难性的。例如说:代码注入可作为许多计算机蠕虫繁殖的温床。 目录 1概说及例子 2代码注入的用途 2....

php:// 访问各个输入/输出流

相关 php.ini 配置 allow_url_fopen :on 默认开启 该选项为on便是激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象文件等。 allow_url_include:off 默认关闭,该选项为on便是允许 包含URL 对象文件等 php://stdin, php://stdout 和 php://stderr...

Gpupdate命令详解

刷新本地和基于 Active Directory 的组策略设置,包括安全设置。该命令可以取代 secedit 命令中已经过时的 /refreshpolicy 选项。 MS-DOS命令语法 gpupdate [/target:{computer|user}] [/force] [/wait:value] [/logoff] [/boot] MS-DOS命令参...

织梦cms dedecms程序安装问题

织梦程序的安装及使用 程序安装使用 1.下载程序解压到本地目录; 2.上传程序目录中的/uploads到网站根目录 3.运行http://xxx.xxx.xxx/install/index.php(xxx.xxx.xxx表示你的域名) ,之后按照安装说明进行程序安装 注意事项: 1、安装时候,数据库地址、数据库用户、密码、数据库名这四项是空间商提供的,如果...

MySQL存储树形数据优化技笔记

1、树形结构应用场景 有时我们需要保存一些树形的数据,比如组织架构、话题讨论、知识管理、商品分类等,这些数据之间存在一种递归关系,很多开发人员想到的第一个解决方案往往是记录每个节点的父节点,例如以下的评论表。 CREATE TABLE comments (     comment_id int(10)  NOT NULL,     paren...

【转】巧用CAT706做掉电检测

相信大家都会遇到这样的情况,当你正在敲一份文档或一段代码时,啪的一下停电啦,我擦……,我的代码……,我的图纸……,我刚写好的文章……。但是在嵌入式系统中也会遇到类似的情况,通常会导致嵌入式系统数据,程序丢失,不能工作,甚至损坏存储系统。而对于核心板的嵌入式系统来说,异常掉电情况下数据不丢失,稳定性是根本。本文基于CAT706介绍一种能够检测到异常掉电,并利...