精华内容
下载资源
问答
  • mysql查询缓存参数配置

    千次阅读 2021-01-18 23:02:49
    举例来说,当同一条查询语句打到mysql服务器,如果配置了查询缓存,就会将这个结果集存放在缓存空间,下一次同一条sql过来时就直接走缓存,这样就可以提升查询效率 1、查看mysql服务器缓存相关配置参数 show status ...

    前言

    使用mysql对数据检索时,为了提升查询性能,引入了缓存的配置,通过设置缓存相关参数,在一定范围内可以大大提升查询效率

    举例来说,当同一条查询语句打到mysql服务器,如果配置了查询缓存,就会将这个结果集存放在缓存空间,下一次同一条sql过来时就直接走缓存,这样就可以提升查询效率

    1、查看mysql服务器缓存相关配置参数

    show status like 'Qcache%';
    

    在这里插入图片描述
    Qcache_free_memory:Query Cache中目前剩余的内存大小,通过这个参数可以较为准确的观察到当前系统的Query Cache是否充足,是否需要增加还是过剩了

    Qcache_lowmem_prunes:多少条query语句因为内存不足而从Query Cache中清除掉,通过Qcache_lowmem_prunes和Qcache_free_memory相互结合,能更清楚的了解到系统中的Query Cache是否真的足够,是否非常频繁的出现因为内存不足而存在Query被清除的现象,这个数字要放在一个较长的时间段看才有意义,如果这个数字在不断增长,表示可能存在较严重的碎片化现象,或者内存很少了

    Qcache_total_blocks:当前Query Cache中block的数量

    Qcache_free_blocks:缓存中相邻内存块的个数,如果该值显示较大,说明Query Cache中的内存碎片较多了

    查询缓存碎片率: Qcache_free_memory /Qcache_total_blocks * 100% ,经验值判断,如果查询碎片率超过20%,可以使用 flush query cache来整理缓存碎片

    mysql中Block的默认大小为4KB,这个值可以手动调整,设置的较大的话,对于大数据的查询有好处,但是如果你实际查询数据时都是小数据,就容易造成内存碎片

    Qcache_hits:表示有多少次命中缓存,我们可以通过这个值来验证我们查询的缓存效果,数字越大效果越理想

    Qcache_inserts:表示多少次未命中而插入,就是说新来的SQL请求在缓存中没有找到,不得不执行查询处理,执行查询处理之后将结果insert到缓存中,这样的情况次数越大,表示查询缓存应用的数量越少,效果也就越不理想

    Qcache_queries_in_cache:当前的Query Cache 中Query数量,即当前的缓存中使用到的缓存查询数量

    Qcache_not_cached:未进入查询缓存的select数量

    2、设置置Query Cache参数

    set GLOBAL query_cache_size=1024000000
    

    或者在my,cnf文件中设置

    注意:

    • query_cache_size(查询缓存大小,QC的单位最小是1024byte,所以如果你设定的一个不是1024的倍数的值,这个值将会被四舍五入到最接近或等于1024的倍数)
    • query_cache_limit,超出此大小的查询将不被缓存,限定了单个查询缓存的最大内存数量(图中表示当前的单条select最大的查询缓存大小超过了1MB之后将不会被缓存)
      在这里插入图片描述

    3、设置Query Cache Type参数

    query_cache_type:缓存类型,决定缓存什么样的查询,这个值不能随便设置,而必须为数字,可选择的数值如下:

    • 0:OFF,相当于禁用(5.7默认禁用了查询缓存,需要在my.cnf中进行设置)
    • 1:ON,缓存所有结果,除非你的select语句显示使用了SQL_NO_CACHE禁用了查询缓存
    • 2:DEAND,只缓存select语句中通过SQL_CACHE指定需要缓存的查询

    在这里插入图片描述
    4、设置Query Block参数

    • query_cache_min_res_unit:缓存块的最小大小query_cache_min_res_unit最小单位是4KB,设置的大点对大数据查询有好处,但是小数据多的话容易产生内存碎片造成资源浪费
    • 单个查询占用缓存的平均值:(query_cache_size - Qcache_free_memory) / Qcache_queries_in_cache
    • 查询缓存利用率:(query_cache_size - Qcache_free_memory)/ query_cache_size * 100%,查询缓存利用率在25%以下说明query_cache_size 设置的过大了,可以适当减小,查询缓存利用率在80%以上,而且 Qcache_lowmem_prunes 》 50说明query_cache_size 设置的有点小,要不就是碎片太多
    • 查询缓存命中率,Qcache_hits / (Qcache_hits + Qcache_inserts) * 100%

    5、查询排序缓存区设置

    在这里插入图片描述

    sort_buffer_size

    • 每个需要排序的线程分配的一个缓存区域,通过设置该参数可以加速 order by 或者group by的操作(在开发过程中,经常碰到对一个大批量查询出来的数据进行order by或者group by的操作,如果设置了这项参数,利用排序缓冲空间,可以大大提升排序的速度)
    • sort_buffer_size是一个connection级别的参数,在每个connection第一次需要使用这个buffer的时候,一次性分配指定数量大小的内存
    • sort_buffer_size不是越大越好,由于是connection级别的参数,过大的设置在遇到高并发场景下可能会很快耗尽系统资源,例如1000个请求的并发的消耗大小为:1000 * sort_buffer_size(2MB) = 2G,这个内存占用就比较吓人了

    本篇主要总结了一些和mysql查询缓存相关的参数配置,合理运用这些参数,可以在一定范围内提升mysql服务器的查询性能,还需要结合实际情况进行反复的调试以达到合理的参数值的配置,本篇到此结束,最后感谢观看!

    展开全文
  • MySQL高级特性四:查询缓存

    万次阅读 2019-02-02 13:16:17
    MySQL在某些场景下也可以实现,但是MySQL还有另一种不同的缓存类型:缓存完整的select查询结果,也就是查询缓存。 MySQL查询缓存保存查询返回的完整结果。当查询命中该缓存,MySQL会like返回结果,跳过了解析、优化...

    很多数据库产品都能够缓存查询的执行计划,对于相同类型的SQL就可以跳过SQL解析和执行计划生成截断。MySQL在某些场景下也可以实现,但是MySQL还有另一种不同的缓存类型:缓存完整的select查询结果,也就是查询缓存。

    MySQL查询缓存保存查询返回的完整结果。当查询命中该缓存,MySQL会like返回结果,跳过了解析、优化和执行截断。

    查询缓存系统会跟踪查询中涉及的每个表,如果这些表发生变化,那么和这个表相关的所有的缓存数据都将失效。这种机制效率看起来比较低,因为数据表变化时很有可能对应的查询结果没有变更,但是这种简单实现代价很小,而这点对于一个非常繁忙的系统来说非常重要。

    查询缓存对应用程序是完全透明的。应用程序无需关心MySQL是通过查询返回的还是实际执行返回的结果。事实上,这两种方式执行的结果是完全相同的。换句话说,查询缓存无需使用任何语法。无论是MySQL开启或关闭查询缓存,对程序都是透明的。

    随着现在的通用服务器越来越强大,查询缓存被发现是一个影响服务器扩展性的因素。它可能成为整个服务器的资源竞争单点,在多核服务器上还可能导致服务器僵死。所以大部分时候应该默认关闭查询缓存,如果查询缓存作用很大的话,可以配置个几十兆的小缓存空间。

    1 MySQL如何判断缓存命中

    MySQL判断缓存命中的方法很简单:缓存存放在一个引用表中,通过一个哈希值引用,这个哈希值包括了如下因素:

    查询语句、当前要查询的数据库、客户端协议的版本等一些其他可能会影响返回结果的信息。

    当判断缓存是否命中时,MySQL不会解析、优化或者参数化查询语句,而是直接使用sql语句和客户端发送过来的其他原始信息。任何字符上的不同,例如空格、注释等都会导致缓存的不命中。所以在编写sql语句的时候,需要特别注意这点。通常使用同一的编码规则是一个好的习惯,在这里这个好习惯会让系统运行的更快。

    当查询语句中有一些不确定的数据时,则不会被缓存。类似包含函数now()或current_date()的查询不会被缓存。事实上,如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、mysql库中的系统表,或者任何包含列级别权限的表,都不会被缓存。

    如果查询中包含一个不确定的函数,MySQL则不会检查查询缓存。这句话是不正确的,因为在检查查询缓存的时候,还没有解析SQL语句,所以MySQL并不知道查询语句中是否包含这类函数。在从检查查询缓存之前,MySQL只做一件事,就是通过一个大小写不敏感的检查来看看sql语句是否以sel开头。

    准确的说法应该是:如果查询语句中包含任何的不确定函数,那么在查询缓存中是不可能找到缓存结果的。因为即使之前刚刚执行了这样的查询,结果也不会放在查询缓存中MySQL在任何时候只要发现不能被缓存的部分,就会禁止这个查询被缓存。

    所以,如果希望换成一个带日期的查询,那么最好将日期提前计算好,而不要直接使用函数。

    因为查询缓存是在完整的select语句的基础上的,而且只是在刚收到sql语句的时候才检查,所以子查询和存储过程都没办法使用查询缓存。在5.1之前的版本中绑定变量也无法使用查询缓存。

    MySQL的查询缓存在很多时候可以提升查询性能,在使用的时候,有一些问题需要特别注意。首先,打开查询缓存对读和写操作都会带来额外的消耗:

    ① 读查询在开始之前必须先检查是否命中缓存。

    ② 如果这个读查询可以被缓存,那么当完成执行后,MySQL若发现查询缓存中没有这个查询,会将其结果存入查询缓存,这会带来额外的系统消耗。

    ③ 这对鞋操作也会有影响,因为当想某个表写入数据的时候,MySQL必须将对应表的所有缓存都设置失效。如果查询缓存非常大或者碎片很多,这个操作就可能会带来很大的系统消耗。

    虽然如此,查询缓存仍然可能给系统带来性能提升。但是,如上所述,这些额外消耗也可能不断增加,在加上对查询缓存操作时一个加锁排他操作,这个消耗可能不容小觑。

    对InnoDB、用户来说,事物的一些特性会限制查询缓存的使用。当一个语句在事物中修改了某个表,MySQL会将这个表的对应的查询缓存都设置失效,事实上InnoDB的多版本特性会暂时将这个修改对其他事物屏蔽。在这个事物提交前,这个表的相关查询时无法被缓存的,所以所有在这个表上面的查询,内部或外部的事物,都只能在改事物提交后才被缓存。因此,长时间运行的事物,会大大降低查询缓存的命中率。

    如果查询缓存使用了很大量的内存,缓存失效操作就可能成为一个非常严重的问题瓶颈。如果缓存中存放了大量的查询结果,那么缓存失效操作时整个系统可能都会僵死一会。因为这个操作时靠一个全局锁操作保护的,所有需要做该操作的查询都需要等待这个锁,而且无论是检测是否命中缓存、还是缓存失效检测都需要等待这个全局锁。

    2 查询缓存如何使用内存

    查询缓存使完全存储在内存中的,所以在配置和使用它之前,我们需要了解它是如何使用内存的。除了查询结果之外,需要缓存的还有很多别的维护相关的数据。这和文件系统有些类似:需要一些内存专门用来确定哪些内存目前是可用的、哪些是已经用掉的、哪些用来存储数据表和查询结果之前的映射、哪些用来存储查询字符串和查询结果。

    这些基本的管理维护数据结构大概需要40kb的内存资源,除此之外,MySQL用于查询缓存的内存被分成一个个的数据块,数据块是变长的。每一个数据块中,存储了自己的类型、大小和存储的数据本身,还外加指向前一个和后一个数据块的指针。数据块的类型有:存储查询结果、存储查询和数据表的映射、存储查询文本等。不同的存储块,在内存使用上没有什么不同,从用户角度来看无需区分他们。

    当服务器启动的时候,它先初始化查询缓存需要的内存。这个内存池初始是一个完整的空闲块。这个空闲块的大小就是你锁配置的查询缓存大小减去用于维护原数据的数据结构所消耗的空间。

    当有查询结果需要缓存的时候,MySQL先从大的空间块中申请一个数据块用于存储结果。这个数据块需要大于参数query_cache_min_res_unit的配置,即使查询结果远远小于此,人需要至少申请query_cache_min_res_unit空间。因为需要在查询开始返回结果的时候就分配空间,而此时是无法预知查询结果到底多大的,所以MySQL无法为每一个结果精确分配大小恰好的缓存空间。

    因为需要先锁住空间块,然后找到合适大小数据库,所以相对来说,分配内存块是一个非常慢的操作。MySQL尽量避免这个操作的次数。当需要缓存一个查询结果的时候,它先选择一个尽可能小的内存块,然后将结果存入其中。如果数据块全部用完,但仍有剩余数据需要存储,那么MySQL会申请一块新的数据块;仍然是尽可能小的数据块,继续存储结果数据。当查询完成时,如果申请的内存空间还有剩余,MySQL会将其释放,并放入空闲内存部分。

    我们上面说的分配内存块,并不是指通过函数malloc()向操作系统申请内存,这个操作只是初次创建查询缓存的时候执行一次。这里分配内存块是指在空闲块列表中找到一个合适的内存块,或者从正在使用的、待淘汰的内存块中回收在使用。也就是说,这里MySQL自己管理一大块内存,而不依赖操作系统的内存管理。

    至此一切看起来都很简单。不过实际情况很复杂。例如,我们假设平均查询结果非常小,服务器在并发的想不通的两个链接返回结果,返回结果后MySQL回收剩余数据块空间时会发现,回收的数据块小于query_cache_min_res_unit,所以不能够直接在后续的内存块分配中使用。那么分配就更复杂一些。

    在收缩第一个查询结果使用的缓存空间时,就会在第二个查询结果之间留下一个空隙,因为小于query_cache_min_res_unit而不能再次被查询缓存使用。这类空隙就成为了内存空间碎片,这在内存管理、文件系统管理上都是经典问题。有很多种情况都会导致碎片,例如缓存失效时,可能导致留下太小的数据块无法在后续缓存中使用。

    3 什么情况下查询缓存能发挥作用

    并不是什么情况下查询缓存都会提高系统性能的。缓存和失效都会带来额外的消耗,所以只有当缓存带来的资源节约大于其本身的资源消耗时才会给系统带来性能提升。这根具体的服务器压力模型有关。

    理论上,可以通过观察打开或者关闭查询缓存时候的系统效率来决定是否需要开启查询缓存。关闭查询缓存时,每个查询都需要完整的执行,每一次写操作执行完成后立刻返回:打开查询缓存时,每次读请求先检查缓存是否命中,如果命中则立刻返回,否则就完整的执行查询,每次写操作则需要检查查询缓存中是否需要失效的缓存,然后在返回结果。

    这个过程还比较简单明了,但是评估打开查询缓存是否能够带来性能提升却并不容易。还有一些外部的因素需要考虑,例如,查询缓存可以降低查询执行的时间,但是却不能减少查询结果传输的网络消耗,如果这个消耗时系统的主要瓶颈,那么查询缓存的作用也很小。

    因为MySQL在show status中只能提供一个全局的性能指标,所以汉南根据此来判断查询缓存是否能够提升性能。很多时候,全局平均不能反映实际情况。例如,打开查询缓存可以使得一个很慢的查询变得非常快,但是也会让其他查询稍微慢一点点。有时候如果能够让某些关键的查询速度更快,稍微降低一下其他查询的速度是值得的。不过,这种情况我们推荐使用sql_cache来优化对查询缓存的使用。

    对于那些需要消耗大量资源的查询通常都是非常适合缓存的。例如一些汇总计算查询count()等。总的来说,对于复杂的select语句都可以使用查询缓存,例如多表join后还需要做排序和分页,这类查询每次执行消耗都很大,但是返回的结果集却很小,非常适合查询缓存。不过需要注意的是,设计的表上update、delete和insert操作相比select来说要非常少才行。

    一个判断查询缓存是否有效的直接数据是命中率,就是使用查询缓存返回结果占总查询的比率。当MySQL接收到一个select查询的时候,要么增加Qcache_hits的值,要么增加Com_select的值。所以查询缓存命中率可以由一下公式计算:Qcache_hits/(Qcache_hits+Com_select)。

    不过查询缓存命中率是一个很难判断的数值。命中率多大才是好的命中率?只要查询缓存带来的效率提升大于查询缓存带来的额外消耗,即使百分之三十的命中率对系统性能提升也有很大好处。另外,缓存了哪些查询也很重要,例如,被缓存的查询本身消耗非常巨大,那么即使缓存命中率非常低,也任然会对系统性能提升有好处。所以,没有一个简单的规则可以判断查询缓存是否对系统有好处。

    任何select语句没有从查询缓存中返回都称为缓存未命中。可能有一下几点原因:

    ① 查询语句无法被缓存,可能是因为查询中包含一个不确定的函数,或者查询结果太大而无法缓存。这都会导致状态值Qcache_not_cached增加。

    ② MySQL从未处理这个查询,所以结果也从不曾被缓存过。

    ③ 还有一种情况是虽然之前缓存了查询结果,但是由于查询缓存的内存用完了,MySQL需要将某些缓存清除,或者由于数据表被修改导致缓存失效。

    如果你的服务器上有大量缓存未命中,但是实际上绝大多数查询都被缓存了,那么一定是有以下几种情况:

    ① 查询缓存还没有完成预热,也就是说,MySQL还没有机会将查询结果缓存起来。

    ② 查询语句之前从未执行过。

    ③ 缓存失效操作太多了。

    缓存碎片、内存不足、数据修改都会导致缓存失效。如果配置了足够的缓存空间,而且query_cache_min_res_unit设置也合理的话,那么缓存失效应该主要是数据修改导致的。可以通过参数com_*来查看数据修改的情况,还可以通过Qcache_lowmem_prunes来查看有多少次失败时由于内存不足导致的。

    在考虑缓存命中率的同时,通常还需要考虑缓存失效带来的额外消耗。一个极端的办法是,对某一个表先做一次只有查询的测试,并且所有的查询都命中缓存,而另一个相同的表则只做修改操作。这时,查询缓存的命中率就是百分百。但因为会给更新操作带来额外的消耗,所以查询缓存并不一定会带来总体效率的提升。这里,所有的更新语句都会做一次缓存失效检查,而检查的结果都是相同的,这会给系统带来额外的资源浪费。所以,如果你只是观察查询缓存的命中率的话,可能完全不会发现这样的问题。

    在MySQL中如果更新操作和带缓存的读操作混合,那么查询缓存带来的好处通常很难衡量。更新操作会不断的使得缓存失效,而同时每次查询还会想缓存中在写入新的数据。所以只有当后续的查询能够在缓存失效前使用缓存才会有效的利用查询缓存。

    如果缓存的结果在失效前没有被任何其他的select语句使用,那么这次缓存操作就是浪费时间和内存。我们可以通过查看com_select和qcache_inserts的相对值来看看是否一致有这种情况发生。如果每次查询操作都是缓存未命中,然后需要将查询结果放到缓存中,那么qcache_inserts的大小应该和com_select相当。所以在缓存完成预热后,我们总希望看到qcache_inserts远远小于com_select。不过由于缓存和服务器内部的复杂和多样性,任然很难说,这个比率是多少才是一个合适的值。

    所以,上面的命中率和inserts和select比率都无法只管的反应查询缓存的效率。那么还有什么只管的办法能够反应查询缓存是否对系统有好处?这里推荐查看另一个指标:命中和写入的比率,即qcache_hits和qcache_inserts的比值。根据经验来看当这个比值岛屿3:1的时候,通常查询缓存时有效的,不过这个比率最好能够达到10:1.如果你的应用没有达到这个比率,那么久可以考虑禁用查询缓存了,除非你能够通过精确的计算得知:命中带来的性能提升大于缓存失效的消耗,并且查询缓存并没有成为系统的瓶颈。

    每一个应用程序都会有一个最大缓存空间,甚至对一些纯读的应用来说也一样。最大缓存空间时能够缓存所有可能查询结果的缓存空间总和。理论上,对多数应用来说,这个数值都会非常大。而实际上,由于缓存失效的原因,大多数应用最后使用的缓存空间都比预想的要小。即使你配置了足够大的缓存空间,由于不断的失效,导致缓存空间一直都不会接近最大缓存空间。

    通常可以通过观察查询缓存内存的实际使用情况,来确定是否需要缩小或扩大查询缓存。如果查询缓存空间长时间都有剩余,那么建议缩小;如果经常由于空间不足而导致查询缓存失效,那么则需要增大查询缓存。不过需要注意,如果查询缓存达到了几十兆这样的数量级,是有潜在危险的。

    另外,可能还需要和系统的其他缓存一起考虑,例如InnoDB的缓存池,或者MyISAM的索引缓存。关于这点无法简单给出一个公式或者比率来判断,因为真正的平衡点与应用程序有很大的关系。

    最好的判断查询缓存是否有效的办法还是通过查看某类查询时间消耗是否增大或者减小来判断。Percona Server通过扩展慢查询可以观察到一个查询是否命中缓存。如果查询缓存没有为系统节省时间,那么最好禁用它。

    4 如何配置和维护查询缓存

    一旦理解查询缓存工作的原理,配置起来就很容易了。它只有很少的参数可供配置:

    ① query_cache_type

    是否打开查询缓存。可以设置OFF、ON或DEMAND、DEMAND表示只有在查询语句中明确写入sql_cache的语句才放入查询缓存。这个变量可以是会话级别的也可以是全局级别的。

    ② query_cache_size

    查询缓存使用的总内存空间,单位是字节。这个值必须是1024的整倍数,否则实际分配的数据会和指定的大小有区别。

    ③ query_cache_min_res_unit

    在查询缓存中分配内存块时的最小单位。

    ④ query_cache_limit

    MySQL讷讷够缓存的最大查询结果。如果查询结果大于这个值,则不会被缓存。因为查询缓存在数据生成的时候就开始尝试缓存数据,所以只有当结果全部返回后,MySQL才知道查询结果是否超出限制。

    如果超出,MySQL则增加状态值qcache_not_cached,并将结果从查询缓存中删除。如果你实现知道有很多这样的情况发生,那么建议在查询语句中加入sql_no_cache来避免查询缓存带来的额外消耗。

    ⑤ query_cache_wlock_invalidate

    如果某个数据表被其他的链接锁住,是否仍然从查询缓存中返回结果。这个参数默认是OFF,这可能在一定程序上会改变服务器的行为,因为这使得数据库可能返回其他线程锁住的数据。将参数设置成ON,则不会从缓存中读取这类数据,但是这可能会增加锁等待。对于绝大多数应用来说无需注意这个细节,默认的通常没有问题。

     

    配置查询缓存通常很简单,但是如果想知道修改这些参数会带来哪些改变,则是一项很复杂的工作。

    减少碎片

    没有什么方法能够完全避免碎片,但是选择合适的query_cache_min_res_unit可以帮你减少由碎片导致的内存空间浪费。设置合适的值可以平衡每个数据块的大小和每次存储结果时内存块申请的次数。这个值太小,则浪费的空间更少,但是会导致更频繁的内存块申请操作;如果这个值设置的太大,那么碎片会很多。调整合适的值其实是在平衡内存浪费和CPU消耗。

    这个参数的最合适的大小和应用程序的查询结果的平均大小直接相关。可以通过内存实际消耗(query_cache_size-qcache_free_memory)/qcache_queries_in_cache计算单个查询的平均缓存大小。如果你的应用程序的查询结果很不均匀,有的结果很大,有的结果很小,那么碎片和反复的内存块分配可能无法避免。如果你发小缓存一个非常大的结果并没有什么意义,那么你可以通过query_cache_limit限制可以缓存的最大查询结果,借此来大大减少大的查询结果的缓存,罪证减少内存碎片的发生。

    还可以通过参数qcache_free_blocks来观察碎片。参数qcache_free_blocks反应了查询缓存中空闲块的多少。最糟糕的情况是,任何两个存储结果的数据块之间都有一个非常小的空间块。所以如果qcache_free_blocks大小恰好达到qcache_total_blocks/2,那么查询缓存就有严重的碎片问题。而如果你还有很多空闲块,而状态值qcache_lowmem_prunes还不断的增加,则说明由于碎片导致了过早的在删除查询缓存结果。

    可以使用命令flush query cache完成碎片整理。这个命令会将所有的查询缓存重新排序,并将所有的空闲空间都聚集到查询缓存的一块区域上。不过需要注意,这个命令并不会讲查询缓存清空,清空缓存由命令resert query cache完成。flush query cache会访问所有的查询缓存,在这期间任何其他的链接都无法访问查询缓存,从而会导致服务器僵死一段时间,使用这个命令的时候需要特别小心着点。另外,根据经验,建议保持查询缓存空间足够小,以便在维护时可以将服务器僵死控制在非常短的时间内。

    提高查询缓存的使用率

    如果查询缓存不在有碎片问题,但你仍然发现命中率很低,还可能是查询缓存的内存空间太小导致的。如果MySQL无法为一个新的查询缓存结果的时候,则会选择删除某个老的缓存结果。

    当由于这个原因导致删除老的缓存结果时,会增加状态值qcache_lowmem_prunes。如果这个值增加的很快,那么可能是有下面两个原因导致的:

    ① 如果还有很快空闲块,那么碎片可能是问题原因。

    ② 如果这时没有空闲块了,就说明在这个系统压力下,你分配的查询缓存空间不够大。可以通过检查状态值qcache_free_memory来查看剩余的内存空间大小。

    如果空闲块很多,碎片很少,也没有什么用于内存导致的缓存失效,但是命中率仍然很低,那么很可能说明,在你的系统压力下,查询缓存并没有什么好处。一定是什么原因导致查询缓存无法为系统服务,例如有大量的更新或者查询语句不能被缓存。

    如果在观察命中率时,任然无法确定查询缓存是否给系统带来了好处,那么可以通过禁用它,然后观察系统性能,在重新打开它,观察性能变化,据此来判断查询缓存是否给系统带来了好处。可以通过将query_cache_size设置成0来关闭查询缓存。改变query_cahe_type的全局值并不会影响已经打开的链接,也不会讲查询缓存的内存释放给系统。

    如何分析和配置查询缓存:

    5 InnoDB和查询缓存

    因为InnoDB有自己的MVCC机制,所以相比其他存储引擎,InnoDB和查询缓存的交互要更加复杂。MySQL4.0中,在事物处理中查询缓存时被禁用的,以后版本中InnoDB会控制在一个事物中是否可以使用查询缓存,InnoDB会同时控制对查询缓存的读和写操作。

    事物是否可以访问查询缓存取决于当前事物ID,以及对应的数据表上是否有锁。每一个InnoDB表的内存数据字典都保存了一个事物ID号,如果当前事物ID小于事物ID,则无法访问查询缓存。

    如果表上有任何的锁,那么对这个表的任何查询语句都是无法被缓存的。例如,某个事物执行了select for update语句,那么在这个锁释放之前,任何其他的事物都无法从查询缓存中读取与这个表相关的缓存结果。

    当事物提交时,InnoDB持有锁,并使用当前的一个系统事物ID更新当前表的计数器。锁一定程度上说明事物需要对表进行修改操作,当然有可能事物获得锁,却不进行任何更新操作,但是如果想更新任何表的内容,获得相应锁则是前提条件。InnoDB将每个表的计数器设置成某个事物ID,而这个事物ID就代表了当前存在的且修改了该表的最大的事物ID。

    那么下面的一些概念也就成立:

    ① 所有大于该表计数器的事物才可以使用查询缓存。例如当前系统的事物ID是5,且事物获取了该表的某些记录的锁,然后进行事物提交操作,那么事物1到4都不应该在读取或者想查询缓存写入任何相关的数据。

    ② 该表的计数器并不是直接更新为对该表进行加锁的事物ID,而是被更新成一个系统事物ID。所以,会发现该事物自身后续的更新操作也无法读取和修改查询缓存。

    查询缓存存储、检索和失效操作都是在MySQL层面完成,InnoDB无法绕过或者延迟这个行为。但InnoDB可以在事物中显示的告诉MySQL何时应该让某个表的查询缓存都失效。在没有外键限制的时候这是必须的,例如某个sql语句有on delete cascade,呢么相关联表的查询缓存也是要一起失效的。

    原则上,在InnoDB的MVCC架构下,当某些修改不影响到查询缓存的效率。还有一些需要注意:

    ① 用多个小表代替一个达标对查询缓存由好处。这个设计将会使得失效策略能够在一个更合适的粒度上进行。当然,不要让这个原则过分影响你的设计,毕竟其他的一些优势可能很容易弥补这个问题。

    ② 批量写入时只需要做一次缓存失效,所以相比单条写入效率更好。

    ③ 因为缓存空间太大,在过期操作的时候可能会导致服务器僵死。一个简单的解决办法就是控制缓存空间的大小query_cache_size,或者直接禁用查询缓存。

    ④ 无法在数据库或者表级别控制查询缓存,但是可以通过sql_cache和sql_no_cache来控制某个select语句是否需要进行缓存。你还可以通过修改会话级别的变量query_cache_type来控制查询缓存。

    ⑤ 对于写密级行的应用来说,直接禁用查询缓存可能会提高系统的性能。关闭查询缓存可以移除所有相关的消耗。

    ⑥ 因为对互斥信号量的竞争,有时直接关闭查询缓存对读密级型的应用也会有好处。如果你希望提高系统的并发,那么最好做一个相关的测试,对比打开和关闭查询缓存时候的性能差异。

    如果不想所有的查询都进入查询缓存,但是又希望某些查询走缓存,那么可以将query_cache_type设置成demand,然后在希望缓存的查询中加上sql_cache。这虽然需要在查询中加入一些额外的语法,但是可以让你非常自由的控制哪些查询需要杯缓存。相反,如果希望缓存多数查询,而少数查询又不希望缓存,那么你可以使用关键字sql_no_cache。

    7 查询缓存的替代方案

    MySQL查询缓存工作的原则是:执行查询最快的方式就是不执行,但是查询仍然需要发送到服务器端,服务器也还需要做一点点工作。如果对于某些查询完全不需要与服务器通信效果会如何呢?这是客户端的缓存可以很大程度上帮你分担MySQL服务器的压力。

    展开全文
  • mysql 开启查询缓存方法与查询例子

    千次阅读 2018-05-11 09:16:38
    开启缓存,设置缓存大小,具体实施如下:1、修改配置文件,windows下是my.ini,linux下是my.cnf;在配置文件的最后追加上: 代码如下复制代码query_cache_type = 1query_cache_size = 600000需要重启mysql生效;那么...

    开启缓存,设置缓存大小,具体实施如下:

    1、修改配置文件,windows下是my.ini,linux下是my.cnf;

    在配置文件的最后追加上:

     代码如下复制代码

    query_cache_type = 1
    query_cache_size = 600000

    需要重启mysql生效;

    那么采用第二种方式;

    b) 开启缓存,两种方式:

    a)使用mysql命令:

     代码如下复制代码

    set global query_cache_type = 1;  
    set global query_cache_size = 600000;

    如果报错:

    query cache is disabled; restart the server with query_cache_type=1...

    在mysql命令行输入

    show variables like "%query_cache%" 查看是否设置成功,现在可以使用缓存了;
    当然如果你的数据表有更新怎么办,没关系mysql默认会和这个表有关系的缓存删掉,下次查询的时候会直接读表然后再缓存

    下面是一个简单的例子:

     代码如下复制代码

    [MySQL@csdba1850 ~]$ MySQL -u root -p
    Enter password:
    Welcome to the MySQL monitor. Commands end with ; or /g.
    Your MySQL connection id is 3
    Server version: 5.0.45-community MySQL Community Edition (GPL)
    Type 'help;' or '/h' for help. Type '/c' to clear the buffer.
    MySQL> set global query_cache_size = 600000;

    设置缓存内存

    Query OK, 0 rows affected (0.00 sec)
    MySQL> set session query_cache_type = ON;

    开启查询缓存

    Query OK, 0 rows affected (0.00 sec)
    MySQL> use test Reading table information for completion 
    of table and column names You can turn off this feature to 
    get a quicker startup with -A Database changed mysql> show tables; 
    +----------------+ | Tables_in_test | +----------------+ | animals | 
    | person | +----------------+ 5 rows in set (0.00 sec) 
    mysql> select count(*) from animals; +----------+ | count(*) 
    | +----------+ | 6 | +----------+ 1 row in set (0.00 sec)

    Qcache_hits表示mysql缓存查询在缓存中命中的累计次数,是累加值。


    mysql> SHOW STATUS LIKE 'Qcache_hits'; +---------------+-------+ 
    | Variable_name | Value | +---------------+-------+ | Qcache_hits 
    | 0 | --0次 +---------------+-------+ 8 rows in set (0.00 sec) 
    mysql> select count(*) from animals; +----------+ | count(*) 
    | +----------+ | 6 | +----------+ 1 row in set (0.00 sec) 
    mysql> SHOW STATUS LIKE 'Qcache%'; +---------------+-------+ 
    | Variable_name | Value | +---------------+-------+ | Qcache_hits | 1 | 

    表示sql在缓存中直接得到结果,不需要再去解析

    +---------------+-------+ 8 rows in set (0.00 sec) 
    mysql> select count(*) from animals; +----------+ 
    | count(*) | +----------+ | 6 | +----------+ 1 row in set (0.00 sec) 
    mysql> select count(*) from animals; +----------+ | count(*) 
    | +----------+ | 6 | +----------+ 1 row in set (0.00 sec) 
    mysql> SHOW STATUS LIKE 'Qcache_hits'; +---------------+-------+ 
    | Variable_name | Value | +---------------+-------+ | Qcache_hits | 3 | 

    上面的sql也是是从缓存中直接取到结果

    +---------------+-------+ 1 row in set (0.00 sec) mysql> insert into animals select 9,'testsds' ; 

    插入数据后,跟这个表所有相关的sql缓存就会被清空掉

    Query OK, 1 row affected (0.00 sec) Records: 
    1 Duplicates: 0 Warnings: 0 mysql> select count(*) from animals; 
    +----------+ | count(*) | +----------+ | 7 | +----------+ 
    1 row in set (0.00 sec) mysql> SHOW STATUS LIKE 'Qcache_hits'; 
    +---------------+-------+ | Variable_name | Value | 
    +---------------+-------+ | Qcache_hits | 3 | 

    还是等于3,说明上一条sql是没有直接从缓存中直接得到的

    +---------------+-------+ 1 row in set (0.00 sec) 
    mysql> select count(*) from animals; +----------+ 
    | count(*) | +----------+ | 7 | +----------+ 
    1 row in set (0.00 sec) mysql> SHOW STATUS LIKE 'Qcache_hits'; 
    +---------------+-------+ | Variable_name | Value | +---------------+-------+ 
    | Qcache_hits | 4 | +---------------+-------+ 1 row in set (0.00 sec) 

    以上的相关内容就是对mysql缓存查询和设置的介绍,望你能有所收获。

    补充

    第一: query_cache_type 使用查询缓存的方式
    一般,我们会把 query_cache_type 设置为 ON,默认情况下应该是ON

     代码如下复制代码
    mysql> select @@query_cache_type;
    +--------------------+
    | @@query_cache_type |
    +--------------------+
    | ON |
    +--------------------+

    query_cache_type有3个值 0代表关闭查询缓存OFF,1代表开启ON,2(DEMAND)代表当sql语句中有SQL_CACHE关键词时才缓存,如:select SQL_CACHE user_name from users where user_id = '100';
    这样 当我们执行 select id,name from tableName; 这样就会用到查询缓存。
    ①在 query_cache_type 打开的情况下,如果你不想使用缓存,需要指明
    select sql_no_cache id,name from tableName;
    ②当sql中用到mysql函数,也不会缓存
     
    当然也可以禁用查询缓存: mysql> set session query_cache_type=off;
    第二: 系统变量 have_query_cache 设置查询缓存是否可用

     代码如下复制代码
    mysql> show variables like 'have_query_cache';
    +------------------+-------+
    | Variable_name | Value |
    +------------------+-------+
    | have_query_cache | YES |

    +------------------+-------+
    上面的显示,表示设置查询缓存是可用的。
    第三: 系统变量 query_cache_size
    表示查询缓存大小,也就是分配内存大小给查询缓存,如果你分配大小为0,
    那么 第一步 和 第二步 起不到作用,还是没有任何效果。

     代码如下复制代码
    mysql> select @@global.query_cache_size;
    +---------------------------+
    | @@global.query_cache_size |
    +---------------------------+
    | 16777216 |
    +---------------------------+

    上面是 mysql6.0设置默认的,之前的版本好像默认是0的,那么就要自己设置下。
    设置 set @@global.query_cache_size=1000000; 这里是设置1M左右,900多K。
    再次查看下

     代码如下复制代码
    select @@global.query_cache_size;
    +---------------------------+
    | @@global.query_cache_size |
    +---------------------------+
    | 999424 |
    +---------------------------+

    显示我们设置新的大小,表示设置成功。
    第四: query_cache_limit 控制缓存查询结果的最大值
    例如: 如果查询结果很大, 也缓存????这个明显是不可能的。
    MySql 可以设置一个最大的缓存值,当你查询缓存数结果数据超过这个值就不会
    进行缓存。缺省为1M,也就是超过了1M查询结果就不会缓存。

     代码如下复制代码
    mysql> select @@global.query_cache_limit;
    +----------------------------+
    | @@global.query_cache_limit |
    +----------------------------+
    | 1048576 |
    +----------------------------+

    这个是默认的数值,如果需要修改,就像设置缓存大小一样设置,使用set
    重新指定大小。
    好了,通过4个步骤就可以 打开了查询缓存,具体值的大小和查询的方式 这个因不同
    的情况来指定了。
    mysql查询缓存相关变量

     代码如下复制代码
    mysql> show variables like '%query_cache%';
    +------------------------------+----------+
    | Variable_name                | Value    |
    +------------------------------+----------+
    | have_query_cache             | YES      |
    | query_cache_limit            | 1048576  |
    | query_cache_min_res_unit     | 4096     |
    | query_cache_size             | 16777216 |
    | query_cache_type             | ON       |
    | query_cache_wlock_invalidate | OFF      |
    +------------------------------+----------+
    6 rows in set (0.00 sec)

    第五:查看缓存的状态

     代码如下复制代码
    mysql> show status like '%Qcache%';
    +-------------------------+----------+
    | Variable_name           | Value    |
    +-------------------------+----------+
    | Qcache_free_blocks      | 11       |
    | Qcache_free_memory      | 16610552 |
    | Qcache_hits             | 10       |
    | Qcache_inserts          | 155      |
    | Qcache_lowmem_prunes    | 0        |
    | Qcache_not_cached       | 21       |
    | Qcache_queries_in_cache | 111      |
    | Qcache_total_blocks     | 256      |
    +-------------------------+----------+
    8 rows in set (0.00 sec)

    MySQL 提供了一系列的 Global Status 来记录 Query Cache 的当前状态,具体如下:
    Qcache_free_blocks:目前还处于空闲状态的 Query Cache 中内存 Block 数目
    Qcache_free_memory:目前还处于空闲状态的 Query Cache 内存总量
    Qcache_hits:Query Cache 命中次数
    Qcache_inserts:向 Query Cache 中插入新的 Query Cache 的次数,也就是没有命中的次数
    Qcache_lowmem_prunes:当 Query Cache 内存容量不够,需要从中删除老的 Query Cache 以给新的 Cache 对象使用的次数
    Qcache_not_cached:没有被 Cache 的 SQL 数,包括无法被 Cache 的 SQL 以及由于 query_cache_type 设置的不会被 Cache 的 SQL
    Qcache_queries_in_cache:目前在 Query Cache 中的 SQL 数量
    Qcache_total_blocks:Query Cache 中总的 Block 数量
     
    第六:检查查询缓存使用情况
    检查是否从查询缓存中受益的最简单的办法就是检查缓存命中率
    当服务器收到SELECT 语句的时候,Qcache_hits 和Com_select 这两个变量会根据查询缓存
    的情况进行递增
    查询缓存命中率的计算公式是:Qcache_hits/(Qcache_hits + Com_select)。

     代码如下复制代码
    mysql> show status like '%Com_select%';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | Com_select    | 1     |
    +---------------+-------+

     
     
    query_cache_min_res_unit的配置是一柄”双刃剑”,默认是4KB,设置值大对大数据查询有好处,但如果你的查询都是小数据 查询,就容易造成内存碎片和浪费。

    查询缓存碎片率 = Qcache_free_blocks / Qcache_total_blocks * 100%

    如果查询缓存碎片率超过20%,可以用FLUSH QUERY CACHE整理缓存碎片,或者试试减小query_cache_min_res_unit,如果你的查询都是小数据量的话。

    查询缓存利用率 = (query_cache_size - Qcache_free_memory) / query_cache_size * 100%

    查询缓存利用率在25%以下的话说明query_cache_size设置的过大,可适当减小;查询缓存利用率在80%以上而且 Qcache_lowmem_prunes > 50的话说明query_cache_size可能有点小,要不就是碎片太多。

    查询缓存命中率 = (Qcache_hits - Qcache_inserts) / Qcache_hits * 100%

    示例服务器 查询缓存碎片率 = 20.46%,查询缓存利用率 = 62.26%,查询缓存命中率 = 1.94%,命中率很差,可能写操作比较频繁吧,而且可能有些碎片。

    转载地址:https://blog.csdn.net/zhwxl_zyx/article/details/44095703

    展开全文
  • MyBatis——查询缓存

    千次阅读 2019-07-16 15:27:38
    一级缓存是基于 PerpetualCache 的 HashMap 的本地缓存,其缓存的作用域为 Session,当 Session flush 或 close 之后,该Session中的所有缓存就会被清空。二级缓存与一级缓存机制相同,默认也是采用PerpetualCache的...

    一、MyBatis的缓存介绍
     和大多数持久层框架一样,MyBatis同样提供了一级缓存和二级缓存的支持。一级缓存是基于 PerpetualCache 的 HashMap 的本地缓存,其缓存的作用域为 Session,当 Session flush 或 close 之后,该Session中的所有缓存就会被清空。二级缓存与一级缓存机制相同,默认也是采用PerpetualCache的HashMap进行存储,不同之处在于其存储作用域为 Mapper(即同一个Namespace),并且可自定义存储源,如 Ehcache、Hazelcast等。
     默认情况下,MyBatis是启用一级缓存的,它是SqlSession级别的,也即同一个SqlSession对象调用相同的Select语句,就会从一级缓存中直接拿到结果,而不是再去查询一次数据库。默认情况下,Select会使用缓存,增删改不使用。当 Session flush 或 close 之后,该Session中的所有 Cache 都将清空。
     MyBatis的缓存机制及二级缓存的工作模式:
    在这里插入图片描述
    二、一级缓存
     MyBatis默认是开启一级缓存的,即在同一个SqlSession中,使用同样的查询条件调用同一个查询方法(调不同的方法即使SQL文完全相同也不会使用一级缓存,当然一般而言同一个接口中不会定义逻辑完全相同的多个方法)时只有第一次会发送SQL到数据库进行查询,后续都会直接从一级缓存中获取缓存结果,但一级缓存在以下情况下会失效:
      1️⃣更改查询条件(这个不算失效,而是本身就没有缓存)
      2️⃣方法中查询使用的SqlSession对象不是同一个,比如在方法中执行了sqlSession.close()之后又新开一个SqlSession
      3️⃣是同一个SqlSession对象,但执行过sqlSession.clearCache();清空了缓存
      4️⃣增删改操作之后,一旦方法中有增删改的操作,SqlSession就会清空缓存

     一级缓存的原理:MyBatis内部缓存使用了一个HashMap,HashMap是键值对的结构,键值对中的key是hashCode + 查询的SqlId(即XxxMapper.xml中的id) + 编写的sql查询语句,键值对的值是执行查询后所获得Java对象。一级缓存的作用域是SqlSession,每次查询先找缓存,找到了就使用,找不到再从数据库查询,查询到数据后会将数据写入一级缓存。

    三、二级缓存
     一级缓存只在同一个SqlSession中有效,但有时我们可能会在多个方法中调用同一个查询方法且参数也有可能相同,在多个方法中必然不能使用同一个SqlSession,这时仅仅使用一级缓存就获取不到数据了,因为一级缓存中缓存的数据在SqlSession提交之后会被清空,这时就需要开启二级缓存。MyBatis中的二级缓存是Mapper级别的,多个SqlSession去操作同一个Mapper的接口方法(SQL)时,这多个SqlSession之间的二级缓存是共用的,即二级缓存是跨SqlSession的。
     1、开启二级缓存的步骤:
      ①在mybatis-config.xml中配置开启二级缓存

    <settings>
    	<!-- 全局映射器启用缓存 -->
    	<setting name="cacheEnabled" value="true" />
    </settings>
    

    在这里插入图片描述
      注意:用二级缓存时Entity类必须实现序列化接口

    @Data
    public class Student implements Serializable {
    	private static final long serialVersionUID = -2777225822411336118L;
    	private String id;
    	private String name;
    	private Integer age;
    	private String email;
    }
    

      ②在XxxMapper.xml中添加一个<cache>:

    <mapper namespace="com.bdm.mappers.StudentMapper">
    	<!-- 缓存的具体方案 -->
    	<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true" />
    	<update id="update" parameterType="com.bdm.entities.Student">
    		UPDATE students SET
    		name=#{name},age=#{age},email=#{email}
    		WHERE
    		id=#{id}
    	</update>
    	<select id="getById" parameterType="string" resultType="com.bdm.entities.Student">
    		SELECT *
    		FROM students WHERE id = #{id}
    	</select>
    </mapper>
    

      测试:

    public class MainTest {
    
    	private static final String SOURCE = "mybatis-config.xml";
    	private static SqlSessionFactory sqlSessionFactory = null;
    	private SqlSession sqlSession = null;
    
    	static {
    		InputStream inputStream;
    		try {
    			inputStream = Resources.getResourceAsStream(SOURCE);
    			sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    	@Before
    	public void before() {
    		sqlSession = sqlSessionFactory.openSession();
    	}
    
    	@Test
    	public void test() {
    		StudentMapper mapper = sqlSession.getMapper(StudentMapper.class);
    		Student s1 = mapper.getById("1");
    		Student s2 = mapper.getById("1");
    		sqlSession.close();
    		sqlSession = sqlSessionFactory.openSession();
    		StudentMapper mapper1 = sqlSession.getMapper(StudentMapper.class);
    		Student s3 = mapper1.getById("1");
    		Student s4 = mapper1.getById("1");
    		System.out.println(s1.toString());
    		System.out.println(s2.toString());
    		System.out.println(s3.toString());
    		System.out.println(s4.toString());
    	}
    
    	@After
    	public void after() {
    		try {
    			sqlSession.commit();
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			sqlSession.close();
    		}
    	}
    }
    

       后台只打印一条SQL语句:说明二级缓存启用了

     2、二级缓存的参数说明

    <cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
    

      关于配置的参数说明如下:
       1️⃣eviction:缓存的回收策略,此处使用的是FIFO(先进先出)的策略,即进入缓存时间最久的对象会先被清理
       2️⃣flushInterval:缓存刷新的频率,每60000毫秒(即1分钟)刷新一次缓存
       3️⃣size:缓存的大小,注意此处是指缓存的对象的个数(默认是1024),而非空间,当缓存的对象达到512个时就会执行eviction中指定的回收策略将对象从缓存中移除
       4️⃣readOnly:缓存中的对象是否是只读的,属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化),这会慢一些,但是安全,因此默认是false
      缓存的回收策略有以下四种可选:
       1️⃣LRU:最近最少使用,移除最长时间不被使用的对象,它是默认
       2️⃣FIFO:先进先出,按对象进入缓存的顺序来移除它们
       3️⃣SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
       4️⃣WEAK:弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
     3、禁用二级缓存

    <select id="getUserById" parameterType="Integer" resultType="User" useCache="false">
    	select * from tbl_user where id=#{id}
    </select>
    

      设置useCache值为false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存
     4、刷新(清空)二级缓存

    <update id="updateUser" parameterType="User" flushCache="true">
    	UPDATE tbl_user SET NAME=#{name},age=#{age} WHERE id=#{id}
    </update>
    

      insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读,所以默认为true,默认情况下为true即刷新缓存,一般不用修改。

    四、一级缓存和二级缓存的使用顺序
     如果你的 MyBatis 使用了二级缓存,并且你的 Mapper 和 select 语句也配置使用了二级缓存,那么在执行 select 查询的时候,MyBatis 会先从二级缓存中取,其次才是一级缓存,即 MyBatis 查询数据的顺序是:

    查不到
    查不到
    二级缓存
    一级缓存
    数据库

    五、MyBatis中使用第三方二级缓存框架
     EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider(MyBatis默认的二级缓存是PerpetualCache)。
     整合步骤:
      ①引入EhCache的依赖或导入相关jar:
       mybatis-ehcache-1.0.2.jar
       ehcache-core-2.7.1.jar
      ②在src根目录下创建EhCache的配置文件:ehcache.xml

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    	<diskStore path="D:\ehcache" />
    	<defaultCache maxElementsInMemory="1000"
    		maxElementsOnDisk="10000000" 
    		eternal="false" 
    		overflowToDisk="false"
    		timeToIdleSeconds="120" 
    		timeToLiveSeconds="120"
    		diskExpiryThreadIntervalSeconds="120" 
    		memoryStoreEvictionPolicy="LRU">
    	</defaultCache>
    </ehcache>
    

       参数说明:
        <diskStore/>:指定数据在磁盘中的存储位置
        <defaultCache>:当借助CacheManager.add(“demoCache”)创建Cache时,EhCache便会采用<defalutCache/>指定的管理策略
       以下属性是必须的:
        a、maxElementsInMemory:在内存中缓存的element的最大数目
        b、maxElementsOnDisk:在磁盘上缓存的element的最大数目,若是0表示无穷大
        c、eternal:设定缓存的elements是否永不过期,如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
        d、overflowToDisk:设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
       以下属性是可选的:
        a、timeToIdleSeconds:当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
        b、timeToLiveSeconds:缓存element的有效生命期,默认是0,也就是element存活时间无穷大
        c、diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小,默认是30MB,每个Cache都应该有自己的一个缓冲区
        d、diskPersistent:在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false
        e、diskExpiryThreadIntervalSeconds:磁盘缓存的清理线程运行间隔,默认是120秒,每隔120s,相应的线程会进行一次EhCache中数据的清理工作
        f、memoryStoreEvictionPolicy:当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
      ③开启ehcache缓存:修改XxxMapper.xml文件,在<cache>中指定使用EhcacheCache

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.bdm.mappers.StudentMapper">
    	<!-- 使用EhCache作为二级缓存管理器 -->
    	<cache type="org.mybatis.caches.ehcache.EhcacheCache" />
    	<update id="update" parameterType="com.bdm.entities.Student">
    		UPDATE students SET
    		name=#{name},age=#{age},email=#{email}
    		WHERE
    		id=#{id}
    	</update>
    	<select id="getById" parameterType="string" resultType="com.bdm.entities.Student">
    		SELECT *
    		FROM students WHERE id = #{id}
    	</select>
    </mapper>
    
    展开全文
  • MyBatis 查询缓存

    千次阅读 2018-01-14 21:03:52
    查询缓存的作用,主要是为了提高查询访问速度。将用户对同一数据的重复查询过程简化,不再每次从数据库查询获取结果数据,从而提高访问速度。 MyBatis的查询缓存机制,根据缓存区的作用域(生命周期)可以划分为2种...
  • MySQL查询缓存的优缺点

    千次阅读 2017-08-17 19:34:05
    与朋友或同事谈到mysql查询缓存功能的时候,个人喜欢把Query Cache比作荔枝, 是非常营养的东西,但是一次性吃太多了,就容易导致上火而流鼻血,虽然不是特别恰当的比喻,但是有很多相似的地方,另外Query Cache有其...
  • MySQL查询缓存的配置

    千次阅读 2018-01-03 16:18:23
    MySQL查询缓存的配置只有以下5个参数。 可以通过 SET GLOBAL query_cache_limit= 40960 配置查询缓存的参数,但这样设置,重启服务器的时候需要重新配置。也可在MySQL的配置文件my.ini中配置,只需添加自己需要的...
  • mysql的查询缓存

    千次阅读 2017-07-09 00:05:25
    提高单台节点的性能无外乎就那么几种方式,缓存是首当其冲的,因为内存的性能比磁盘高的太多。缓存也是一种典型的空间换时间的策略 缓存的实现也有太多的方式,从静态页面缓存到服务端动态缓存,再到数据库级别缓存...
  • Mysql 不使用查询缓存

    千次阅读 2020-06-03 10:34:34
    Mysql 不使用查询缓存Mysql 不使用查询缓存关闭Mysql 缓存临时命令关闭缓存永久关闭查询缓存修改sql语句 Mysql 不使用查询缓存 有时候在开发过程中,需要测试查询查询的实际性能,这时候就需要关闭查询缓存。不使用...
  • springboot jpa 查询缓存问题解决

    千次阅读 2020-10-13 08:45:15
    spring.jpa.open-in.view: false springboot 2.x以后这个参数默认是true ,遇到多线程dml db的话 要把这个改成false 不然 springboot jpa 就查 缓存了每次都一样 ,
  • 前两天总结了一下二级缓存和查询缓存的关系,但是又有一个新的问题,就是查询缓存缓存到二级缓存的数据,在第三次(第一次缓存中没有数据,查询数据库将对应的ID值存入到二级缓存中去,第二次如果是同一个Session...
  • 二:mybatis查询缓存基本介绍 缓存:将相同查询条件的sql语句执行一遍后所得到的结果存在内存或者某种缓存介质当中,当下次遇到一模一样的查询sql时候不在执行sql与数据库交互,而是直接从缓存中获取结果,减少...
  • MySQL查询缓存

    千次阅读 2018-01-02 10:09:42
    MySQL查询缓存保存查询返回的完整结果。当查询命中缓存,MySQL会立刻返回结果,跳过了解析,优化和执行阶段。 查询缓存执行过程:  1.通过一个大小写不敏感的检查看看SQL语句是不是以SEL开头。  2.若是以SEL...
  • Hibernate 二级缓存和查询缓存

    千次阅读 2018-11-11 17:19:05
    一级缓存:  1,在session上面有一个一级缓存;一级缓存的生命周期和session相同,一级缓存最大生命周期就是一个线程;在web环境下面,session的最大生命周期就是一次请求;  2,一级缓存可以用来干嘛?  1,只能有限的提高...
  • MySQL查询缓存与缓冲区的区别

    千次阅读 2020-02-23 16:05:43
    最近在研究mysql时,发现查询缓存和缓冲池是两个比较容易混淆的点,在这里简单提一下二者的联系与区别。 正文 查询缓存 首先看下mysql的结构图,如下所示: 可以看到,查询缓存作用于第二层,即核心服务层。 其主要...
  • MySQL高级-MySQL查询缓存优化

    千次阅读 2021-01-26 20:47:23
    开启Mysql的查询缓存,当执行完全相同的SQL语句的时候,服务器就会直接从缓存中读取结果,当数据被修改,之前的缓存会失效,修改比较频繁的表不适合做查询缓存。 2 操作流程 1. 客户端发送一条查询给服务器; 2. ...
  • 附:MySQL8.0为什么取消了查询缓存 MySQL 8.0: Retiring Support for the Query Cache MySQL服务器团队有一篇关于此的详细博客,其中Matt Lord说: 尽管MySQL Query Cache旨在提高性能,但它存在严重的可伸缩性问题...
  • Hibernate 二级缓存 和 查询缓存

    千次阅读 2016-02-05 16:49:33
    二级缓存和查询缓存都相当于一个map。 二级缓存缓存的key为id,value为实体对象。一般load,get ,iterate使用到二级缓存,list()需要结合查询缓存使用。 iterate和list区别如下: iterate不需要开启查询...
  • mysql不要使用查询缓存

    千次阅读 2019-05-14 11:08:24
    查询缓存的失效非常频繁,只要有对一个表的更新,这个表上所有的查询缓存都会被清空。因此很可能你费劲的把结果存起来,还没使用呢,就被更新全清空了。对于更新压力大的数据库来说,查询缓存的命中率非常低。除非你...
  • 但是实际上 mysql 也提供了缓存,mysql 里面的缓存是查询缓存,可以把我们查询过的语句缓存下来,下一次查询的时候有可能就直接从缓存返回(缓存命中)。 当然使用 mysql 缓存也不是没有坏处,mysql 多了个管理缓存...
  • JPA之JPQL查询缓存

    千次阅读 2018-07-03 11:21:56
    此时为了执行效率,需要除去重复发送的SQL,需要添加查询缓存。 在 persistence.xml 配置文件中 节点中添加: ... < properties > ... <!--开启查询缓存--> < property name = "hibernate.cache....
  • mysql 查询缓存设置

    千次阅读 2018-02-27 20:58:08
    +——————————+———+| Variable_name | Value |+——————————+———+| have_query_cache | YES | –查询缓存是否可用| query_cache_limit | 1048576 | –可缓存具体查询结果的最大值| query_c...
  • Oracle 清楚查询缓存

    千次阅读 2017-05-08 10:24:24
    ALTER SYSTEM FLUSH SHARED_POOL ;  alter system flush BUFFER_CACHE ;
  • Spring如何配置查询缓存? Ehcache可以对页面、对象、数据进行缓存,同时支持集群/分布式缓存。 一、准备工作 如果你的系统中已经成功加入Spring、Hibernate;那么你就可以进入下面Ehcache的准备工作。 ehcache....
  • MySQL关闭查询缓存(QC)的两种方法

    千次阅读 2019-03-26 16:59:02
    MySQLQuery Cache 会缓存select 查询,安装时默认是开启的,但是如果对表进行INSERT, UPDATE, DELETE, TRUNCATE, ALTER TABLE, DROP TABLE, or DROP DATABASE等操作时,之前的缓存会无效并且删除。这样一定程度上也...
  • mysql清空查询缓存

    千次阅读 2017-06-16 22:30:09
    对一条sql进行优化时,发现原本很慢的一条sql(将近1分钟) 在第二次运行时, 瞬间就完成了(0.00sec)这是因为mysql对同一条sql进行了缓存,服务器直接从上次的查询...可通过如下方法清空查询缓存reset query cache;
  • SQL查询缓存

    千次阅读 2017-04-11 12:18:07
    本教程适合于那些对缓存SQL查询以减少数据库连接与执行的负载、提高脚本性能感...这样一个系统通过把SQL查询的结果缓存到系统的一个文件中存储,从而阻止连接数据库,构造查询与取得返回结果而提高了响应时间。 有些
  • cache可以用于select、find、value和column方法,以及其衍生方法,使用cache方法后,在缓存有效期之内不会再次进行数据库查询操作,而是直接获取缓存中的数据,关于数据缓存的类型和设置可以参考缓存部分。...
  •  缓存:一般人的理解是在内存中的一块空间,可以将二级缓存配置到硬盘。用白话来说,就是一个存储数据的容器。我们关注的是,哪些数据需要被放入二级缓存。  作用:降低应用程序直接读写数据库的频率,从而提高...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 677,706
精华内容 271,082
关键字:

查询缓存