TiDB控制执行计划有没有好的建议?是使用Hints更好还是通过执行计划绑定更好?

目前TiDB优化器还是存在不少执行计划走偏的情况,对于这种情况,大家在项目组中主要采用的哪种方法控制执行计划?

  • (1)全部使用Hints,会侵入SQL代码;
SELECT /*+ USE_INDEX(t1, idx1), HASH_AGG(), HASH_JOIN(t1) */ count(*) FROM t t1, t t2 WHERE t1.a = t2.b;
  • (2)全部使用执行计划绑定,通过DDL形式,不侵入SQL代码;
CREATE [GLOBAL | SESSION] BINDING FOR BindableStmt USING BindableStmt;
  • (3)部分使用Hints,部分使用执行计划绑定;

在实际工作中,发现无论使用Hints,还是使用执行计划绑定,都存在不少问题,所以想请教下大家在实际项目中更偏向于采用哪种方式控制执行计划。

先简单说下,在实际项目中使用这两种方式控制执行计划的一些问题:

  • 使用Hints的问题:
    (1)需要侵入SQL代码逻辑;
    (2)对于MyBatis里这种动态SQL的,该方式控制执行计划可能会导致某些实际SQL有正向的优化效果,但是对于某些实际SQL会有反向的影响(即导致执行计划错误);
    (3)一旦涉及一些表结构的修改(如索引等),每次都需要在所有的功能代码中查询是否有用到该索引进行Hints指定,所以维护还是比较麻烦;

  • 使用执行计划绑定:
    (1)同样对于MyBatis那种动态SQL,可能一条动态SQL,实际出来会有几十种情况,即可能实际执行的SQL有几十种,因此为每条实际执行的动态SQL添加执行计划绑定,还是比较费时费力,同样后期维护起来,也是异常痛苦;

绑定执行计划的动机是因为不绑定的话 TiDB 确实没选对执行计划吗?

  1. 使用 hints 管理工作在业务,但 DBA 改结构把索引删了,业务语句会报错
  2. 使用 binding 管理工作在 DBA,但业务 sql 稍微改下 patten 比如多个 as 就无法命中 binding

目前TiDB优化器还是存在不少执行计划走偏的情况

可以具体问题具体分析,官方也在不断提供 Optimizer Fix Controls

1 个赞

是的,目前发现有两种情况:
1、有明显更好的执行计划,没有走,走了比较差的那个;
2、明显更好的执行计划并且TiDB优化器评估estCost也更低,但是最终没有走;

删除索引并不会导致使用原有的Hints报错

你们用的比较细致,我们是只要cpu高了就扩资源。执行计划基本上没有绑定过。

你们用的比较细致,我们是只要发现慢了,就扩资源,几乎没绑定过执行计划。

用hint放应用代码里,mybatis 就hint跟着条件变,这玩意你也不能搞太复杂吧,不能把所有逻辑都放mybatis里吧 :joy_cat:
换索引问题,我一般比较少的加索引hint,都是改关联方式

HASH_AGG,只要根节点有这个算子。
强烈推荐尝试一下tiflash+mpp。大概率会有奇效。

1 个赞

我们全部的SQL逻辑都统一放在MyBatis里,目前我们通过控制执行计划的方式指定关联方式、指定关联顺序和指定使用索引都有

这个我们有用到,目前我们联机查询尽量走TiKV,批量分析走TiFlash,目前TiFlash而言对并发高一点的查询还是不那么友好,官方也建议走TiFlash的QPS不超过50,说明还是有一定的局限。

资源还是比较宝贵的,一直扩资源治标不治本 :joy:

SQL 放mybatis里没问题,我说的是你别光在一个SQL中来回拼啊,多写几个SQL,到时候mybatis里的逻辑更复杂了 :joy_cat:

你们是土豪

这么细致

Hints和绑定不应该大范围使用,迫不得已的时候多是用在多表关联,固定关联方式和关联顺序。
几乎所有数据库的优化器在处理多表关联时,都是一个不小的挑战。

1 个赞

这不现实,因为组合查询太常见了

确实有点豪

说是这么说,但是目前TiDB的优化器不太智能,还是有不少执行计划会走偏,绑定也是情非得已

需要注意,就是走tiflash不一定是mpp。有的时候执行计划里面有tiflash但是只是去做扫描的话,可能没多大提升,反而有回退。

局限确实有,你用的还是6.5这个版本tiflash没有资源管控,缺少一些算子落盘的策略。
这些到了7.5就会好很多。内存不太容易炸了。稳定很多。