执行计划缓存,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是将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执行计划进行缓存的基本原理和流程如下图所示:

- 响应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





总结
GaussDB(for MySQL)通过缓存执行计划,可以提升Prepared Statement的性能。特别是针对Range Scan的测试集,性能提升可达2倍左右。未来我们会支持越来越多的查询场景,性能加速值得期待。
执行计划缓存,Prepared Statement性能跃升的秘密的更多相关文章
- SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰
本文出处:http://www.cnblogs.com/wy123/p/7190785.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...
- 谈一谈SQL Server中的执行计划缓存(下)
简介 在上篇文章中我们谈到了查询优化器和执行计划缓存的关系,以及其二者之间的冲突.本篇文章中,我们会主要阐述执行计划缓存常见的问题以及一些解决办法. 将执行缓存考虑在内时的流程 上篇文章中提到了查询优 ...
- 谈一谈SQL Server中的执行计划缓存(上)
简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...
- 浅析SQL Server中的执行计划缓存(上)
简介 我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询 ...
- 【MS SQL】通过执行计划来分析SQL性能
原文:[MS SQL]通过执行计划来分析SQL性能 如何知道一句SQL语句的执行效率呢,只知道下面3种: 1.通过SQL语句执行时磁盘的活动量(IO)信息来分析:SET STATISTICS IO O ...
- SQL Server 执行计划缓存
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/内存池/缓冲区 概述 了解执行计划对数据库性能分析很重要,其中涉及到了语句性能分析与存储,这也是写这篇文章的目的,在了解执行计划之 ...
- SQL SERVER 2012 执行计划走嵌套循环导致性能问题的案例
开发人员遇到一个及其诡异的的SQL性能问题,这段完整SQL语句如下所示: declare @UserId INT declare @PSANo VAR ...
- SQL Sever 2008性能分析之执行计划
一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试 2的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<Inside Microsoft SQL ...
- SQL点滴27—性能分析之执行计划
原文:SQL点滴27-性能分析之执行计划 一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<I ...
- SQL性能分析之执行计划
一直想找一些关于SQL语句性能调试的权威参考,但是有参考未必就能够做好调试的工作.我深信实践中得到的经验是最珍贵的,书本知识只是一个引导.本篇来源于<Inside Microsoft SQL S ...
随机推荐
- 使用 QuickTime Player 将手机投屏到旧版 Macbook pro
由于旧版的 MacBook Pro 不支持 AirPlay,我们可以通过Mac系统自带的应用程序[QuickTime Player]来进行投屏操作. 以下是具体的步骤: 首先,使用USB数据线将你的 ...
- [AHOI2002] Kitty猫基因突变
我们不妨将所有权值打到一棵树上,这很容易想到. 考虑暴力,如果我们选择了 \(w\) 个点,修改后我们会从叶子节点依次合并去计算贡献. 很显然我们可以动态规划维护. \(f[p][w][0/1/2]\ ...
- 深入理解 Netty FastThreadLocal
作者:vivo 互联网服务器团队- Jiang Zhu 本文以线上诡异问题为切入点,通过对比JDK ThreadLocal和Netty FastThreadLocal实现逻辑以及优缺点,并深入解读源码 ...
- 入手react的 第一坑
npm verb cli /usr/local/bin/node /usr/local/bin/npm npm info using npm@9.8.1 npm info using node@v18 ...
- JS逆向实战25——某壳找房模拟登录+百度喵星人指纹加密破解.
声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 目标 目标网站 aHR0c ...
- React生命周期函数(迭代合并:react 16.3)
本文分两部分,上面的是react16.3,下部分是老版本 react 16.3生命周期更新解析 ------ 老react版本生命周期 1.组件生命周期的执行次数 只执行一次: constructor ...
- QT(6)-QStandardItemModel
@ 目录 1 说明 2 函数 2.1 构造函数 2.2 追加列\行 2.3 清除.删除并返回指定行或列 2.4 查找 2.5 设置水平\垂直表头项目 2.6 获得模型索引 2.7 插入 2.8 根项目 ...
- 7/10 luoguRound 10 庆典 div3T1
#include<bits/stdc++.h> using namespace std; int m,n,x; int arr[100005]; int maxi = -1,maxn = ...
- 测试技术:开源测试工具 jenkins、Sonar
http://www.cnblogs.com/itech/archive/2011/11/23/2260009.html Jenkins入门总结 基于 Jenkins 快速搭建持续集成环境 https ...
- DiscuzQ官方最新v3.0.220211源码编译搭建教程和官方部署教程,适合二开(已本地编译通过,无任何错误)
经过长达半个月的研究! 完成这篇DiscuzQ官方最新版本v3.0.220211的源码编译和官方部署教程.适合喜欢二次开发的小伙伴们,已经通过本地编译测试,保证没有任何错误. 具体教程在我搭建的dzq ...