通读MySQL的查询缓存(一)

开课吧开课吧锤锤2021-05-12 10:08

    Java编程语言是一种简单、面向对象、分布式、解释型、健壮安全、与系统无关、可移植、高性能、多线程和动态的语言。如今Java已经广泛应用于各个领域的编程开发。

Java

    我们知道,缓存的设计思想在RDBMS数据库中无处不在,就拿号称2500w行代码,bug堆积如山的Oracle数据库来说,SQL的执行计划可以缓存在librarycache中避免再次执行相同SQL发生硬解析(语法分析->语义分析->生成执行计划),SQL执行结果缓存在RESULTCACHE内存组件中,有效的将物理IO转化成逻辑IO,提高SQL执行效率。

    MySQL的QueryCache跟Oracle类似,缓存的是SQL语句文本以及对应的结果集,看起来是一个很棒的Idea,那为什么从MySQL4.0推出之后,5.6中默认禁用,5.7中被deprecated(废弃)以及8.0版本被Removed,今天就聊聊MySQLQueryCache的前世今生。

    QueryCache介绍

    MySQL查询缓(QC:QueryCache)在MySQL4.0.1中引入,查询缓存存储SELECT语句的文本以及发送给客户机的结果集,如果再次执行相同的SQL,Server端将从查询缓存中检索结果返回给客户端,而不是再次解析执行SQL,查询缓存在session之间共享,因此,一个客户端生成的缓存结果集,可以响应另一个客户端执行同样的SQL。

Java

    回到开头的问题,如何判断SQL是否共享?

    通过SQL文本是否完全一致来判断,包括大小写,空格等所有字符完全一模一样才可以共享,共享好处是可以避免硬解析,直接从QC获取结果返回给客户端,下面的两个SQL是不共享滴,因为一个是from,另一个是From。

--SQL 1
select id, balance from account where id = 121;
--SQL 2
select id, balance From account where id = 121;

    下面是Oracle数据库通过SQL_TEXT生成sql_id的算法,如果sql_id不一样说明就不是同一个SQL,就不共享,就会发生硬解析。

#!/usr/bin/perl -w
use Digest::MD5  qw(md5 md5_hex md5_base64);
use Math::BigInt;
my $stmt = "select id, balance from account where id = 121\0"; 
my $hash = md5 $stmt; 
my($a,$b,$msb,$lsb) = unpack("V*",$hash);
my $sqln = $msb*(2**32)+$lsb;
my $stop = log($sqln) / log(32) + 1;
my $sqlid = '';
my $charbase32 = '0123456789abcdfghjkmnpqrstuvwxyz';
my @chars = split '', $charbase32;
for($i=0; $i < $stop-1; $i++){
  my $x = Math::BigInt->new($sqln);
  my $seq = $x->bdiv(32**$i)->bmod(32);
  $sqlid = $chars[$seq].$sqlid;
}
print "SQL is:\n    $stmt \nSQL_ID is\n    $sqlid\n";

    大家可以发现SQL1和SQL2通过代码生成的sql_id值是不一样,所以不共享。

SQL is:    select id, balance from account where id = 121 
SQL_ID is  dm5c6ck1g7bds
SQL is:    select id, balance From account where id = 121 
SQL_ID is  6xb8gvs5cmc9b

    如果让你比较两个Java代码文件的内容的有何差异,只需要将这段代码理解透了,就可以改造实现自己的业务逻辑。

    以上就是开课吧开课吧老师敖丙的“通读MySQL的查询缓存(一)”一文,更多Java教程相关内容尽在开课吧广场Java教程频道!

有用
分享
全部评论快来秀出你的观点
登录 后可发表观点…
发表
暂无评论,快来抢沙发!
高并发编程训练营