DOC菜单

SQL计划管理(SPM)

SQL Plan Management是一组执行SQL绑定以手动干扰SQL执行计划的功能。这些函数包括SQL绑定,基线捕获和基线演进。

SQL结合

SQL绑定是SPM的基础。这<一个href="//m.rzhenli.com/docs/optimizer-hints.md">优化器提示文档介绍如何使用提示选择特定的执行计划。然而,有时您需要在不修改SQL语句的情况下干预执行选择。使用SQL绑定,您可以选择指定的执行计划,而不需要修改SQL语句。

创建一个绑定

创建全球的|会议捆绑BINDABLESTMT.使用BINDABLESTMT.

该语句在GLOBAL或SESSION级别绑定SQL执行计划。目前,TiDB中支持的可绑定SQL语句(BindableStmt)包括选择删除更新, 和插入/代替选择子查询。

具体而言,两种类型的这些说法不能绑定到由于语法冲突的执行计划。请参见下面的例子:

- 键入一个:通过使用`join`关键字获取笛卡尔产品的语句,而不是使用`关键字指定相关的列。创建全球的捆绑为了选择t t1加入t t2使用选择t t1加入t t2- 键入二:`删除`使用`的语句,包含`关键字。创建全球的捆绑为了删除T1.使用T1.加入T2.T1.一个T2.一个使用删除T1.使用T1.加入T2.T1.一个T2.一个

您可以使用等效语句绕过语法冲突。例如,您可以通过以下方式重写上述语句:

——第一次重写type 1语句:为join关键字添加一个using子句。创建全球的捆绑为了选择t t1加入t t2使用一个使用选择t t1加入t t2使用一个- 第二次语句的第二次重写:删除“加入”关键字。创建全球的捆绑为了选择t t1t t2使用选择t t1t t2- 重写类型的两个语句:从`delete`语句中删除`使用的`关键字。创建全球的捆绑为了删除T1.T1.加入T2.T1.一个T2.一个使用删除T1.T1.加入T2.T1.一个T2.一个

笔记:

的执行计划绑定时插入/代替陈述选择子查询时,需要指定要绑定的优化器提示选择子查询,而不是插入/代替关键词。否则,按预期的优化器暗示不生效。

这里有两个例子:

- 提示在以下陈述中生效。创建全球的捆绑为了插入进入T1.选择T2.在哪里一个>1b1使用插入进入T1.选择/ * + use_index (@sel_1 t2) * /T2.在哪里一个>1b1- 提示无法在以下陈述中生效。创建全球的捆绑为了插入进入T1.选择T2.在哪里一个>1b1使用插入/ * + use_index (@sel_1 t2) * /进入T1.选择T2.在哪里一个>1b1

如果在创建执行计划绑定时没有指定范围,则默认范围为SESSION。TiDB优化器将绑定的SQL语句规范化,并将它们存储在系统表中。在处理SQL查询时,如果规范化语句匹配系统表中的一个绑定SQL语句和系统变量tidb_use_plan_baselines被设置为(默认值是),TIDB然后使用相应的优化器提示进行此语句。如果有多个可匹配的执行计划,则优化器选择最低昂贵的一个才能绑定。

归一化是一个过程,它将SQL语句中的常量转换为变量参数,并显式地为查询中引用的表指定数据库,并对SQL语句中的空格和换行符进行标准化处理。请看下面的例子:

选择t在哪里一个>1- 标准化:选择测试t在哪里一个>

当一个SQL语句在全球和session在绑定的执行计划,因为优化忽略了在全球范围内绑定的执行计划时遇到的会话绑定,在会话范围盾在执行计划中这句话的约束执行计划在全球范围内。

例如:

- 创建一个全局绑定,并在此绑定中使用`sort merge连接方式指定。创建全球的捆绑为了选择T1.T2.在哪里T1.IDT2.ID使用选择/ * + merge_join(T1,T2)* /T1.T2.在哪里T1.IDT2.ID——这个SQL语句的执行计划使用了GLOBAL绑定中指定的' sort merge join '。解释选择T1.T2.在哪里T1.IDT2.ID——创建另一个SESSION绑定,并在这个绑定中使用' hash join '指定。创建捆绑为了选择T1.T2.在哪里T1.IDT2.ID使用选择/ * + hash_join(t1,t2)* /T1.T2.在哪里T1.IDT2.ID——在该语句的执行计划中,使用了SESSION绑定中指定的' hash join ',而不是GLOBAL绑定中指定的' sort merge join '。解释选择T1.T2.在哪里T1.IDT2.ID

当第一个选择正在执行声明,优化器添加了sm_join (t1, t2)通过GLOBAL作用域中的绑定提示语句。中执行计划的顶部节点解释结果是MergeJoin。当第二个选择语句执行时,优化器使用SESSION作用域中的绑定而不是GLOBAL作用域中的绑定,并添加hash_join(t1,t2)提示的语句。中执行计划的顶部节点解释结果是hashjoin。

每个标准化的SQL语句只能创建一个绑定创建绑定在一个时间。当为同一个标准化SQL语句创建多个绑定时,最后创建的绑定将被保留,所有以前的绑定(创建和发展的)都被标记为已删除。但是会话绑定和全局绑定可以共存,并且不受此逻辑的影响。

此外,当您创建绑定时,TIDB要求会话处于数据库上下文中,这意味着当客户端连接时指定了数据库或数据库使用$ {}执行。

原始SQL语句和绑定语句在规范化和删除提示后必须具有相同的文本,否则绑定将失败。举几个例子:

  • 这个绑定可以成功创建,因为参数化和提示删除前后的文本是相同的:选择*从测试。t哪里>?

    创建捆绑选择t在哪里一个>1使用选择t指数idx.在哪里一个>2
  • 此绑定将失败,因为原始的SQL语句被处理为选择*从测试。t哪里>?,而绑定的SQL语句不同的处理选择*从测试。t where b>?

    创建捆绑选择t在哪里一个>1使用选择t指数idx.在哪里b>2

笔记:

为了准备/执行语句和使用二进制协议执行的查询,需要为实际查询语句创建执行计划绑定,而不是为准备/执行陈述。

删除绑定

降低全球的|会议捆绑BINDABLESTMT.

此语句在GLOBAL或SESSION级别删除指定的执行计划绑定。默认范围是SESSION。

一般情况下,SESSION范围内的绑定主要用于测试或特殊情况。要使绑定在所有TiDB进程中生效,需要使用GLOBAL绑定。创建的SESSION绑定将屏蔽相应的GLOBAL绑定,直到SESSION结束,即使SESSION绑定在会话关闭之前被删除。在本例中,没有绑定生效,计划由优化器选择。

下面的例子是基于<一个href="//m.rzhenli.com/docs/tidb/stable/#create-a-binding">创建绑定其中,会话绑定屏蔽全局绑定:

- 删除会话范围内创建的绑定。降低会议捆绑为了选择T1.T2.在哪里T1.IDT2.ID——重新查看SQL执行计划。解释选择T1.T2.在哪里T1.IDT2.ID

在上面的示例中,会话范围中的丢弃绑定屏蔽全局范围中的相应绑定。优化器不添加sm_join (t1, t2)提示的语句。中执行计划的顶部节点解释result不固定为MergeJoin。相反,最上面的节点是由优化器根据成本估计独立选择的。

笔记:

执行删除全球绑定滴在当前tidb服务器实例缓存结合并改变相应行的状态在系统表中“删除”。这种说法不直接删除系统表中的记录,因为其他tidb服务器实例需要阅读“已删除”的地位砸在自己的高速缓存相应的约束力。对于与“已删除”状态,这些系统表中的记录,在每100绑定信息租赁(默认值是3S, 和300年代的绑定上,后台线程触发一个回收和清除操作更新时间10点前绑定信息租赁(确保所有tidb-server实例已经读取'deleted'状态并更新了缓存)。

查看绑定

展示全球的|会议绑定showlikeorwhere

该语句根据绑定更新时间从最近到最早的顺序,在GLOBAL或SESSION级别输出执行计划绑定。默认范围是SESSION。目前显示绑定输出八列,如下所示:

列名称 请注意
original_sql 参数化后的原始SQL语句
bind_sql. 带有提示的绑定SQL语句
default_db. 默认数据库
地位 状态包括使用,删除无效的,被拒绝,并等待验证
create_time. 创建时间
更新时间 更新时间
Charset. 字符集
排序 订购规则
来源 创建绑定的方式,包括手册(由创建[全球]结合SQL语句),捕获(由tidb自动捕获),发展(由TiDB自动演化)

结合疑难解答

选择@@会议last_plan_from_binding

此语句使用系统变量<一个href="//m.rzhenli.com/docs/system-variables.md">last_plan_from_binding要显示上次执行的语句使用的执行计划是否来自绑定。

另外,当你使用时解释格式='verbose'语句查看SQL语句的查询计划,如果SQL语句使用了绑定,则解释声明将返回警告。在这种情况下,您可以检查警告消息以了解SQL语句中使用哪种绑定。

——创建全局绑定。创建全球的捆绑为了选择t使用选择t——使用' explain format = 'verbose'语句检查SQL执行计划。检查警告消息以查看查询中使用的绑定。解释格式'verbose'选择t展示警告

基线捕获

启用基线捕获,设置tidb_capture_plan_baselines..默认值为离开

笔记:

因为自动绑定创建功能依赖<一个href="//m.rzhenli.com/docs/statement-summary-tables.md">声明摘要,请确保在使用自动绑定之前启用语句摘要。

启用自动绑定创建后,将遍历语句摘要中的历史SQL语句绑定信息租赁(默认值是3S),并为出现至少两次的SQL语句自动创建绑定。对于这些SQL语句,TiDB会自动绑定Statement Summary中记录的执行计划。

但是,TIDB不会自动捕获以下类型的SQL语句的绑定:

  • 解释解释分析陈述。
  • 在TiDB内部执行的SQL语句,例如选择用于自动加载的统计信息的查询。
  • SQL语句绑定到手动创建的执行计划。

为了准备/执行语句和使用二进制协议执行的查询,TiDB自动捕获实际查询语句的绑定,而不是准备/执行陈述。

笔记:

由于TiDB有一些嵌入式SQL语句,以确保某些功能的正确性,在默认情况下基线捕获自动屏蔽这些SQL语句。

基线进化

基线演进是TiDB v4.0中引入的SPM的一个重要特性。

随着数据更新,先前绑定的执行计划可能不再是最优的。基线演化特性可以自动优化绑定的执行计划。

此外,基线演变,在一定程度上,还可以避免由统计信息的变化引起的抖动引起的执行计划。

使用

使用下面的语句来启用自动绑定演化:

全球的tidb_evolve_plan_baselines

的默认值tidb_evolve_plan_baselines离开

警告:

  • 基线演变是一个实验特征。可能存在未知的风险。这是不是建议您在生产环境中使用。
  • 该变量被强制设置为离开直到基线演化特性变得普遍可用(GA)。如果尝试启用此功能,则返回一个错误。如果您已经在生产环境中使用过此功能,请尽快禁用它。如果您发现绑定状态不符合预期,请联系PingCAP的技术支持以获得帮助。

自动绑定,进化功能启用后,如果优化器选择最优的执行计划是不绑定的执行计划中,优化标志计划作为执行计划,核查等待。在每一个绑定信息租赁(默认值是3S)间隔被选择,并使用具有在实际执行时间以最少的费用的结合执行计划相比要被验证的执行计划。如果要验证的方案具有更短的执行时间(用于比较的当前标准是要验证的计划的执行时间比2/3的结合执行计划的不再),该计划被标记为可用的捆绑。下面的例子描述上述过程。

假设表t定义如下:

创建桌子t一个intbint钥匙一个钥匙b

执行上表下面的查询t

选择t在哪里一个<100.b<100.

在上面定义的表中,很少行满足a <100.条件。但由于某种原因,优化器错误地选择了全表扫描而不是使用索引的最佳执行计划一个.你可以先使用下面的语句来创建一个绑定:

创建全球的捆绑为了选择t在哪里一个<100.b<100.使用选择t指数一个在哪里一个<100.b<100.

当上面的查询再次执行时,优化器选择索引一个(受上面创建的绑定的影响)以减少查询时间。

假设在表上执行插入和删除操作t,越来越多的行相遇了a <100.条件和减少行数与之相遇B'100条件。此时,使用索引一个在约束下可能不再是最佳计划。

结合进化可以解决这样的问题。当优化识别表中的数据变化时,它生成用于查询使用索引执行计划b.但是,由于存在当前计划的绑定,因此不会采用和执行此查询计划。相反,此计划存储在后端evolution列表中。在进化过程中,如果这一计划被证实具有比当前执行计划的一个明显的执行时间更短,使用指数一个、索引b将添加到可用的绑定列表中。在此之后,当再次执行查询时,优化程序首先生成使用索引的执行计划b并确保这个计划是在绑定列表中。然后,优化采用并执行该计划,以减少数据更改后的查询时间。

为了减少自动演进对集群的影响,可以使用以下配置:

  • tidb_evolve_plan_task_max_time.限制每个执行计划的最大执行时间。默认值为600年代.在实际的验证过程中,最大的执行时间也仅限于经过验证的执行计划的不超过两倍的时间。
  • tidb_evolve_plan_task_start_time.00:00 +0000默认情况下)和tidb_evolve_plan_task_end_time23:59 + 0000默认情况下)来限制时间窗口。

笔记

因为基线演进会自动创建一个新的绑定,当查询环境发生变化时,自动创建的绑定可能会有多个行为选择。注意以下事项:

  • 基线演变仅发展了具有至少一个全局绑定的标准化SQL语句。

  • 由于创建一个新的绑定删除所有以前的绑定(用于标准化的SQL语句),自动进化绑定将在手动创建一个新的结合被删除。

  • 在进化期间保留与计算过程相关的所有提示。这些提示如下:

    暗示 描述
    memory_quota 可用于查询的最大内存。
    use_toja 优化器是否将子查询转换为Join。
    use_cascades 是否使用级联优化器。
    no_index_merge. 优化器是否使用索引合并作为读取表的选项。
    read_consistent_replica 读表时是否强制启用“Follower Read”。
    max_execution_time. 为查询的最长持续时间。
  • read_from_storage.是一个特殊的提示,因为它指定是否在读取表时从TIKV或来自TIFlash读取数据。由于TIDB提供隔离读取,因此当隔离条件发生变化时,这提示对演进执行计划产生了很大影响。因此,当该提示存在于最初创建的绑定中时,TIDB忽略了所有进化的绑定。

升级的清单

在群集升级期间,SQL Plan Management(SPM)可能会导致兼容性问题并使升级失败。要确保升级成功,您需要包含以下列表进行升级预填充:

  • 当您从早于V5.2.0(即,V4.0,V5.0,V5.1和)与当前版本的版本升级,确保tidb_evolve_plan_baselines升级前禁用。要禁用此变量,请执行以下步骤。

    ——检查“tidb_evolve_plan_baseline”在早期版本中是否被禁用。选择@global.tidb_evolve_plan_baselines——如果' tidb_evolve_plan_baseline '仍然是启用的,禁用它。全球的tidb_evolve_plan_baselines离开
  • 在从v4.0升级到当前版本之前,需要检查新版本中与可用SQL绑定对应的所有查询的语法是否正确。如果存在语法错误,请删除相应的SQL绑定。要做到这一点,请执行以下步骤。

    - 检查与要升级的版本中的可用SQL绑定对应的查询。选择bind_sql.mysql.bind_info在哪里地位'使用'- 验证新版本的测试环境中的上述SQL查询的结果。bind_sql_0.bind_sql_1.——在语法错误的情况下(error 1064 (42000): You have an error In your SQL syntax),删除相应的绑定。- 对于任何其他错误(例如,找不到表),表示语法兼容。不需要其他操作。