首页 > 其他分享 >执行计划缓存,Prepared Statement性能跃升的秘密

执行计划缓存,Prepared Statement性能跃升的秘密

时间:2023-06-02 15:03:19浏览次数:53  
标签:语句 缓存 Prepared 计划 Statement 执行

摘要:一起看一下GaussDB(for MySQL)是如何对执行计划进行缓存并加速Prepared Statement性能的。

本文分享自华为云社区《执行计划缓存,Prepared Statement性能跃升的秘密》,作者: GaussDB 数据库。

引言

在数据库系统中,SQL(Structured Query Language)语句输入到系统后,一般要经历:词法语法解析(parse)、重写(resolve)、优化(optimize)、执行(execute)的过程。词法语法分析,重写和优化,这三个阶段会生成SQL语句的执行计划 (plan)。当SQL语句存在多种执行计划的时候,优化器会从这许多的执行计划中挑选出一个它认为最优的(通常是占用系统资源最少的,包括CPU以及IO等)作为最终的执行计划供执行器执行。生成执行计划的过程会消耗较多的时间,特别是存在许多可选的执行计划时。

图1:SQL语句执行

执行计划缓存,Prepared Statement性能跃升的秘密_执行计划

Prepared Statement是将SQL语句中的值用占位符替代,可以视为将SQL语句模板化或者说参数化。当执行PREPARE语句时,传统MySQL将对指定的语句进行词法语法解析和重写,如上图①②。该阶段称为预编译阶段。Prepared Statement的优势在于一次编译、多次运行,省去了预编译阶段需要的时间。随后发出EXECUTE命令时,MySQL将对编译阶段生成的结构执行优化,即上图的③,生成对应的执行计划并执行,把输出结果返回到客户端。例如:

PREPARE stmt FROM ‘SELECT * FROM t WHERE t.a = ?’;
SET @var = 2;
EXECUTE stmt USING @var;

传统MySQL的Prepared Statement只会节省SQL语句的解析及重写过程需要的时间,但是对于一条SQL语句,如文章开头所述,优化SQL语句并生成执行计划需要耗费大量的资源以及时间。如果能将该Prepared Statement语句对应的最终执行计划进行缓存,当执行EXECUTE语句的时候,就可以直接使用已缓存的执行计划,从而就可以跳过SQL语句生成执行计划的整个过程,进而可以提高语句的执行性能。为此,GaussDB(for MySQL) 提供了Prepared Statement执行计划缓存特性。

接下来一起看一下GaussDB(for MySQL)是如何对执行计划进行缓存并加速Prepared Statement性能的。

执行计划缓存工作原理

GaussDB(for MySQL)对Prepared Statement执行计划进行缓存的基本原理和流程如下图所示:

执行计划缓存,Prepared Statement性能跃升的秘密_SQL_02

  • 响应EXECUTE,执行查询。
  • 通过is_plan_cached过程来查看当前Query的执行计划是否已经被缓存。
  • 如果已经被缓存,优化器将对当前的Query缓存的执行计划进行初始化,根据执行计划的上下文还原执行计划,然后利用还原的执行计划继续执行。
  • 如果没有被缓存,在执行完Query优化生成执行计划之后,通过is_query_cachable过程验证当前执行计划是否可以被缓存。
  • 如果满足缓存条件,执行计划将会被缓存(调用cache_JOIN_plan),以便以后的EXECUTE语句可以利用该缓存的计划进行执行。
  • 如果不能缓存,通过传统的MySQL执行流程(优化,生成执行计划然后执行)执行EXECUTE语句。

执行计划缓存管理

  • 执行计划缓存功能开关

GaussDB(for MySQL)引入了一个新的系统参数rds_plan_cache来开关Prepared Statement执行计划缓存功能。

rds_plan_cache:该参数可以设置为ON/OFF。分别代表开启和关闭执行计划缓存。该参数是Session/Global级别的参数。

  • 查看执行计划缓存情况

GaussDB(for MySQL)提供了两个状态变量供用户查看或者验证Prepared Statement执行计划是否被缓存,以及在执行时是否命中了缓存的执行计划。

  • cached_plan_count:显示有多少个Prepared Statement缓存了执行计划。这是一个Global级别的状态变量。
  • cached_plan_hits:显示EXECUTE执行过程中命中了缓存的执行计划的次数。这是一个Session/Global状态。

下面举例来看一下Prepared Statement是如何利用了执行计划缓存特性的:

SET @a = 'two';
SET @b = 3;
PREPARE stmt FROM "SELECT * FROM t1 WHERE b = ? AND c = ?";
EXECUTE stmt USING @a,@b;

执行结果如下:

a b c
6 two 3

再次执行Prepared Statement:

EXECUTE stmt USING @a,@b;
a b c
6 two 3

第三次执行Prepared Statement:

execute stmt using @a,@b;
a b c
6 two 3

通过cached_plan_count和cached_plan_hits查看stmt执行计划是否被缓存,以及在执行时是否命中了缓存的执行计划。

SHOW SESSION STATUS LIKE "cached_plan%";

显示结果如下:

Variable_name Value
Cached_plan_count 1
Cached_plan_hits 2

从显示结果可以看出,第一次执行EXECUTE语句的时候,Prepared Statement对执行计划进行了缓存,即可以看到Cached_plan_count为1; 之后执行两次EXECUTE语句,都命中了执行计划缓存,所以可以看到Cached_plan_hits变成了2。

缓存的执行计划如何失效

为了保持当前缓存的执行计划是尽可能最优的,GaussDB(for MySQL)定义了如下规则来对当前缓存的计划进行失效,并重新生成执行计划:

  • 执行计划相关表的记录数更改超过总记录数的20%。
    这意味着当前表的记录数如果插入/删除超过20%的记录,当前缓存计划将失效并在优化后重新缓存。注:记录数是根据统计数据估计的。所以最好先对表进行Analyze。
  • 表定义进行了更改。
    例如,执行计划相关表上进行的DDL将导致缓存计划无效,并在优化后重新缓存。
  • 如果系统变量Optimizer_switch中影响执行计划生成的选项值进行了更改,则缓存的计划将失效,并在优化后重新缓存。
  • 系统字符集发生变化,与缓存的计划不同时,将导致缓存计划失效,并在优化后重新缓存。

执行计划缓存功能当前的一些限制

GaussDB(for MySQL)的Prepared Statement的目的是节约查询的优化时间。对于通过并行查询优化的大查询,也就是数据量相对庞大的查询,这些查询大部分的执行时间是集中在执行计划的执行阶段。对于该类型的查询,优化时间相比执行时间而言可以忽略不计,所以GaussDB(for MySQL)没有对并行查询计划进行缓存。另外,GaussDB(for MySQL)对于Prepared statement 缓存执行计划的能力还在逐步增强中,比如当前只支持单表的SELECT查询语句,暂时还不支持UNION操作。

执行计划缓存性能测试结果

对于使用执行计划缓存和不使用执行计划缓存的场景,基于Sysbench测试集进行了性能测试对比,从测试结果可以看出,在启用执行计划缓存后,各类业务性能均有提升。注意:这些测试只代表相对数字,并不代表实际性能。

测试环境配置如下:

数据集 : 8 个表,每个表1000万行
测试服务器:Intel(R) Xeon(R) CPU E5-2690 v4 @ 2.60GHz 2 physical cores 56 processors 460G memory

执行计划缓存,Prepared Statement性能跃升的秘密_缓存_03

执行计划缓存,Prepared Statement性能跃升的秘密_SQL_04

执行计划缓存,Prepared Statement性能跃升的秘密_MySQL_05

执行计划缓存,Prepared Statement性能跃升的秘密_执行计划_06

执行计划缓存,Prepared Statement性能跃升的秘密_Prepared Statement_07

总结

GaussDB(for MySQL)通过缓存执行计划,可以提升Prepared Statement的性能。特别是针对Range Scan的测试集,性能提升可达2倍左右。未来我们会支持越来越多的查询场景,性能加速值得期待。


点击关注,第一时间了解华为云新鲜技术~

标签:语句,缓存,Prepared,计划,Statement,执行
From: https://blog.51cto.com/u_15214399/6402722

相关文章

  • ABP - 缓存模块(1)
    1.与.NETCore缓存的关系和差异ABP框架中的缓存系统核心包是Volo.Abp.Caching,而对于分布式缓存的支持,abp官方提供了基于Redis的方案,需要安装Volo.Abp.Caching.StackExchangeRedis集成包。默认的情况下,在我们使用ABPCLI创建ABP框架模板项目的时候已经集成了这个包......
  • 3月5日周老师缓存面试题资料
    找班主任,要周老师的路线发一下面试突击班,第一天开班有6000+人在线~!!!希望大家紧张起来,今年竞争尤其激烈,新来的同学要加把劲~!今天主题:缓存面试题周老师提升面试成功率给到对方你有思想,有个人见解redis为什么快,TPS/QPS是多少,解决了项目什么问题?1,我讲的redis第一版,之后今年新讲的redi......
  • java map缓存数据自动过期
     packageztest;importjava.util.Date;importjava.util.HashMap;importjava.util.Iterator;importjava.util.Map;importjava.util.Timer;importjava.util.TimerTask;/***页面跳转时产生一个token*带到页面*页面保存时校验token**防止重复提交......
  • 实战:实现缓存和数据库一致性方案
    哈喽大家好,我是阿Q!最近不是正好在研究canal嘛,刚巧前两天看了一篇关于解决缓存与数据库一致性问题的文章,里边提到了一种解决方案是结合canal来操作的,所以阿Q就想趁热打铁,手动来实现一下。架构文中提到的思想是:采用先更新数据库,后删除缓存的方式来解决并发引发的一致性问题;采用异......
  • Spring Boot缓存注解使用案例
    一、spring-boot-cache缓存1、pom<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId><version>2.6.7</version></dependency>2、main启动类加入@EnableCachi......
  • 146. LRU 缓存
    主要是利用LinkedHashMap的功能LinkedHashMap继承了HashMap学到了LinkedHashMap维护双向链表的方法LinkedHashMap的Entry加入了一个before和after,用于维护Entry的加入顺序。next维护各个桶的顺序。回忆LinkedHashMap源码记得看:https://blog.csdn.net/weixin......
  • 图解LeetCode——146. LRU 缓存
    一、题目请你设计并实现一个满足 LRU(最近最少使用)缓存约束的数据结构。实现LRUCache类:LRUCache(intcapacity)以正整数作为容量 capacity初始化LRU缓存intget(intkey)如果关键字key存在于缓存中,则返回关键字的值,否则返回-1。voidput(intkey,intva......
  • cassandra cpp driver中bind list——用cass_statement_bind_collection函数
     CassErrorinsert_into_collections(CassSession*session,constchar*key,constchar*items[]){CassErrorrc=CASS_OK;CassStatement*statement=NULL;CassFuture*future=NULL;CassCollection*collection=NULL;constchar**item=NULL;c......
  • 内存泄漏、缓存溢出?C和C++,哪个更懂得管理内存质量?
    一、c/c++程序内存区域划分c和c++的内存区域划分是十分相似的,因为c++是完全兼容c语言,是c语言的面向对象的升级版。接下来看如下图:程序的内存区域被划分成6个区域。内核空间、栈、内存映射段、堆、数据段、代码段。下面是对相关内存区域名词解释:栈又叫堆栈--非静态局部变量/函数参数......
  • 前端浏览器缓存和HTTP缓存
    缓存缓存优点:减少冗余的数据传输;减轻服务器的压力;加快浏览器加载网页的速度。分类:强缓存和协商缓存 强缓存:服务器不需要发送资源给客户端,客户端直接从缓存中取有关头字段:Cache-Control、Expires,两者同时存在时,前者优先级更高Expires:当客户端向服务器发送请求,服务......