执行计划管理 (SPM)

执行计划管理(SPM)是TiDB中的功能,包括执行计划绑定、自动捕获绑定和自动演进绑定。执行计划绑定允许在不修改SQL的情况下选择执行计划,创建、删除和查看绑定。自动捕获绑定在符合条件的查询上生成绑定,提供升级时的计划回退防护。自动演进绑定则在数据变化后优化已有绑定的执行计划,以适应新的数据分布。升级检查确保SPM功能在版本升级中的兼容性。
摘要由CSDN通过智能技术生成

执行计划管理,又称 SPM (SQL Plan Management),是通过执行计划绑定,对执行计划进行人为干预的一系列功能,包括执行计划绑定、自动捕获绑定、自动演进绑定等。

执行计划绑定 (SQL Binding)

执行计划绑定是 SPM 的基础。在优化器 Hints 中介绍了可以通过 Hint 的方式选择指定的执行计划,但有时需要在不修改 SQL 语句的情况下干预执行计划的选择。执行计划绑定功能使得可以在不修改 SQL 语句的情况下选择指定的执行计划。

创建绑定

 

CREATE [GLOBAL | SESSION] BINDING FOR BindableStmt USING BindableStmt;

该语句可以在 GLOBAL 或者 SESSION 作用域内为 SQL 绑定执行计划。目前,如下 SQL 类型 (BindableStmt) 可创建执行计划绑定:SELECTDELETEUPDATE 和带有 SELECT 子查询的 INSERT/REPLACE

注意

绑定的优先级高于手工添加的 Hint,即在有绑定的时候执行带有 Hint 的语句时,该语句中控制优化器行为的 Hint 不会生效,但是其他类别的 Hint 仍然能够生效。

其中,有两类特定的语法由于语法冲突不能创建执行计划绑定,例如:

 

-- 类型一:使用 `JOIN` 关键字但不通过 `USING` 关键字指定关联列的笛卡尔积 CREATE GLOBAL BINDING for SELECT * FROM t t1 JOIN t t2 USING SELECT * FROM t t1 JOIN t t2; -- 类型二:包含了 `USING` 关键字的 `delete` 语句 CREATE GLOBAL BINDING for delete FROM t1 USING t1 JOIN t2 ON t1.a = t2.a USING delete FROM t1 USING t1 JOIN t2 ON t1.a = t2.a;

可以通过等价的 SQL 改写绕过这个语法冲突的问题。例如,上述两个例子可以改写为:

 

-- 类型一的第一种改写:为 `JOIN` 关键字添加 `USING` 子句 CREATE GLOBAL BINDING for SELECT * FROM t t1 JOIN t t2 USING (a) USING SELECT * FROM t t1 JOIN t t2 USING (a); -- 类型一的第二种改写:去掉 `JOIN` 关键字 CREATE GLOBAL BINDING for SELECT * FROM t t1, t t2 USING SELECT * FROM t t1, t t2; -- 类型二的改写:去掉 `delete` 语句中的 `USING` 关键字 CREATE GLOBAL BINDING for delete t1 FROM t1 JOIN t2 ON t1.a = t2.a USING delete t1 FROM t1 JOIN t2 ON t1.a = t2.a;

注意

在对带 SELECT 子查询的 INSERT/REPLACE 语句创建执行计划绑定时,需要将想要绑定的优化器 Hints 指定在 SELECT 子查询中,而不是 INSERT/REPLACE 关键字后,不然优化器 Hints 不会生效。

例如:

 

-- Hint 能生效的用法 CREATE GLOBAL BINDING for INSERT INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1 USING INSERT INTO t1 SELECT /*+ use_index(@sel_1 t2, a) */ * FROM t2 WHERE a > 1 AND b = 1; -- Hint 不能生效的用法 CREATE GLOBAL BINDING for INSERT INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1 USING INSERT /*+ use_index(@sel_1 t2, a) */ INTO t1 SELECT * FROM t2 WHERE a > 1 AND b = 1;

如果在创建执行计划绑定时不指定作用域,隐式作用域 SESSION 会被使用。TiDB 优化器会将被绑定的 SQL 进行“标准化”处理,然后存储到系统表中。在处理 SQL 查询时,只要“标准化”后的 SQL 和系统表中某个被绑定的 SQL 语句一致,并且系统变量 tidb_use_plan_baselines 的值为 on(其默认值为 on),即可使用相应的优化器 Hint。如果存在多个可匹配的执行计划,优化器会从中选择代价最小的一个进行绑定。

标准化:把 SQL 中的常量变成变量参数,对空格和换行符等做标准化处理,并对查询引用到的表显式指定数据库。例如:

 

SELECT * FROM t WHERE a > 1 -- 以上语句标准化后如下: SELECT * FROM test . t WHERE a > ?

注意

在进行标准化的时候,被逗号 , 连接起来的多个常量会被标准化为 ... 而不是 ?

例如:

 

SELECT * FROM t limit 10 SELECT * FROM t limit 10, 20 SELECT * FROM t WHERE a IN (1) SELECT * FROM t WHERE a IN (1,2,3) -- 以上语句标准化后如下: SELECT * FROM test . t limit ? SELECT * FROM test . t limit ... SELECT * FROM test . t WHERE a IN ( ? ) SELECT * FROM test . t WHERE a IN ( ... )

因此包含单个常量的 SQL 语句和包含被逗号连接起来多个常量的 SQL 语句,在被绑定时会被 TiDB 视作不同的 SQL 语句,需要分别创建绑定。

值得注意的是,如果一条 SQL 语句在 GLOBAL 和 SESSION 作用域内都有与之绑定的执行计划,因为优化器在遇到 SESSION 绑定时会忽略 GLOBAL 绑定的执行计划,该语句在 SESSION 作用域内绑定的执行计划会屏蔽掉语句在 GLOBAL 作用域内绑定的执行计划。

例如:

 

-- 创建一个 global binding,指定其使用 sort merge join CREATE GLOBAL BINDING for SELECT * FROM t1, t2 WHERE t1.id = t2.id USING SELECT /*+ merge_join(t1, t2) */ * FROM t1, t2 WHERE t1.id = t2.id; -- 从该 SQL 的执行计划中可以看到其使用了 glo

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天读点书学堂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值