暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

TiDB执行计划绑定

wzf0072 2025-02-18
166

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


创建绑定


方法1:根据 SQL
    语法:CREATE [GLOBAL | SESSION] BINDING FOR BindableStmt USING BindableStmt;
    支持SQL类型:SELECT、DELETE、UPDATE 和带有 SELECT 子查询的 INSERT/REPLACE。
    优先级
        绑定的优先级高于手工添加的 Hint
        SESSION优先级高于GLOBAL
        如果在创建执行计划绑定时不指定作用域,隐式作用域 SESSION 会被使用。TiDB 优化器会将被绑定的 SQL 进行“标准化”处理,然后存储到系统表中。在处理 SQL 查询时,只要“标准化”后的     SQL 和系统表中某个被绑定的 SQL 语句一致,并且系统变量 tidb_use_plan_baselines 的值为 on(其默认值为 on),即可使用相应的优化器 Hint。如果存在多个可匹配的执行计划,优化器会从中选择代价最小的一个进行绑定。
    每个标准化的 SQL 只能同时有一个通过 CREATE BINDING 创建的绑定。对相同的标准化 SQL 创建多个绑定时,会保留最后一个创建的绑定,之前的所有绑定(创建的和演进出来的)都会被删除。但 session 绑定和 global 绑定仍然允许共存,不受这个逻辑影响。
    创建失败
        语法冲突(处理办法:SQL 改写绕过这个语法冲突的问题)
            类型一:使用 `JOIN` 关键字但不通过 `USING` 关键字指定关联列的笛卡尔积
            类型二:包含了 `USING` 关键字的 `delete` 语句
        在对带 SELECT 子查询的 INSERT/REPLACE 语句创建执行计划绑定时,需要将想要绑定的优化器 Hints 指定在 SELECT 子查询中,而不是 INSERT/REPLACE 关键字后,不然优化器 Hints 不会生效。
        需要注意的是原始 SQL 和绑定 SQL 在参数化以及去掉 Hint 后文本必须相同,否则创建会失败

方法2:历史执行计划( 根据历史执行计划创建绑定目前为实验特性,存在未知风险,请勿在生产环境中使用。)
    语法:CREATE [GLOBAL | SESSION] BINDING FROM HISTORY USING PLAN DIGEST 'plan_digest';
    使用 plan_digest 为 SQL 语句绑定执行计划,在不指定作用域时默认作用域为 SESSION。所创建绑定的适用 SQL、优先级、作用域、生效条件等与根据 SQL 创建绑定相同。

    限制
        该功能是根据历史的执行计划生成 hint 而实现的绑定,历史的执行计划来源是 Statement Summary Tables,因此在使用此功能之前需开启系统变量 tidb_enable_stmt_summary
目前,该功能仅支持根据当前实例中的 statements_summary 和 statements_summary_history 表中的执行计划生成绑定。如果发现有 can't find any plans 的情况,请尝试连接集群中其他 TiDB 节点重试。
    对于带有子查询的查询、访问 TiFlash 的查询、3 张表或更多表进行 Join 的查询,目前还不支持通过历史执行计划进行绑定。
步骤
使用此绑定方式时,你需要先从 statements_summary 中找到需要绑定的执行计划对应的 plan_digest,再通过 plan_digest 创建绑定。
1、从 Statement Summary Tables 的记录中查找执行计划对应的 plan_digest。
2、使用 plan_digest 创建绑定
CREATE BINDING FROM HISTORY USING PLAN DIGEST '4e3159169cc63c14b139a4e7d72eae1759875c9a9581f94bb2079aae961189cb';
3、创建完毕后可以查看绑定,验证绑定是否生效。
SHOW BINDINGS\G;
SELECT * FROM t WHERE a = 1;
SELECT @@LAST_PLAN_FROM_BINDING;


删除绑定
    方法1:根据 SQL 语句删除绑定
        DROP [GLOBAL | SESSION] BINDING FOR BindableStmt;
    方法2:根据 sql_digest 删除绑定
        DROP [GLOBAL | SESSION] BINDING FOR SQL DIGEST 'sql_digest';
    执行 DROP GLOBAL BINDING 会删除当前 tidb-server 实例缓存中的绑定,并将系统表中对应行的状态修改为 'deleted'。该语句不会直接删除系统表中的记录,因为其他 tidb-server 实例需要读取系统表中的 'deleted' 状态来删除其缓存中对应的绑定。对于这些系统表中状态为 'deleted' 的记录,后台线程每隔 100 个 bind-info-lease(默认值为 3s,合计 300s)会触发一次对 update_time 在 10 个 bind-info-lease 以前的绑定(确保所有 tidb-server 实例已经读取过这个 'deleted' 状态并更新完缓存)的回收清除操作。

变更绑定状态
    语法:SET BINDING [ENABLED | DISABLED] FOR BindableStmt;
作用域:该语句可以在 GLOBAL 作用域内变更指定执行计划的绑定状态,默认作用域为 GLOBAL,该作用域不可更改。

查看绑定
    语法:SHOW [GLOBAL | SESSION] BINDINGS [ShowLikeOrWhere];
    该语句会按照绑定更新时间由新到旧的顺序输出 GLOBAL 或者 SESSION 作用域内的执行计划绑定,在不指定作用域时默认作用域为 SESSION。目前 SHOW BINDINGS 会输出 11 列。

排查绑定
    方法1:使用系统变量 last_plan_from_binding 显示上一条执行语句是否采用 binding 的执行计划。SELECT @@[SESSION.]last_plan_from_binding;
    方法2:使用 explain format = 'verbose' 语句查看 SQL 语句的查询计划。如果 SQL 语句使用了 binding,可以接着执行 show warnings 了解该 SQL 语句使用了哪一条 binding。

缓存绑定
    每个 TiDB 实例都有一个 LRU (Least Recently Used) Cache 对绑定进行缓存,缓存的容量由系统变量 tidb_mem_quota_binding_cache 进行控制。缓存会影响绑定的使用和查看,因此你只能使用和查看存在于缓存中的绑定。
如需查看绑定的使用情况,可以执行 SHOW binding_cache status 语句。该语句无法指定作用域,默认作用域为 GLOBAL。该语句可查看缓存中可用绑定的数量、系统中所有可用绑定的数量、缓存中所有绑定的内存使用量及缓存的内存容量。 

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论