Query plan在index索引上解析出full table scan operator

为提高效率,请提供以下信息,问题描述清晰能够更快得到解决:


若提问为性能优化、故障排查类问题,请下载脚本运行。终端输出的打印结果,请务必全选并复制粘贴上传。

3 个赞

explain中存在stats:pseudo信息,建议先进行analyze

stats:pseudo 表示可能因为没有统计信息,或者统计信息过旧,不会用统计信息来进行估算。执行计划的文档里面有提及过这个关键字的意思,不过可能标识得不够清楚。

2 个赞

是的,是有一定概率出现自动analyze不及时,导致不能命中索引的情况。可以参考业务量调整自动analyze的时间和阈值,时间注意默认是不带时区的。
https://docs.pingcap.com/zh/tidb/stable/statistics#自动更新

参考一下这里的解决方案

这时有以下两种手段来避免这个情况:

  • 修改手动收集统计信息中提到的 WITH NUM TOPN 参数。TiDB 会将出现频率前 x 大的数据单独储存,之后的数据再储存到 Count-Min Sketch 中。因此可以调大这个值来避免一个比较大的值和一个比较小的值被哈希到一起。在 TiDB 中,这个参数的默认值是 20,最大可以设置为 1024。
  • 修改统计信息的收集-手动收集中提到的 WITH NUM CMSKETCH DEPTHWITH NUM CMSKETCH WIDTH 两个参数,这两个参数会影响哈希的桶数和碰撞概率,可是适当调大来减少冲突概率,同时它会影响统计信息的内存使用,可以视具体情况来调整。在 TiDB 中, DEPTH 的默认值是 5, WIDTH 的默认值是 2048。

@小王同学 技术大拿,求指导

麻烦通过 explain analyze + SQL 文本 方式反馈下 SQL 真实的执行计划,以及表结构,如果方便的话也可以导出下表的统计信息,参考下:https://docs.pingcap.com/zh/tidb/v4.0/statistics#导出统计信息

2 个赞

那有可能是统计信息过旧导致原来的执行计划发生变化,走到了 tiflash 的存储的引擎,现在手工执行 SQL 执行计划是正常的,可以考虑绑定执行计划,参考:
https://docs.pingcap.com/zh/tidb/v4.0/sql-plan-management#执行计划绑定-sql-binding

1 个赞

1.如果 statement 是 item_id in (?,?...) 这种 id 形式不固定的,应该只需要绑定一次,因为 SQL 语句参数化之后都变成了 where item_id in ( ... ) 这种形式,你可以具体测试下效果;
2.item_id in (?,?,…)(item_id = ? OR item_id = ?) OR (item_id = ? OR item_id = ?) 这两种类型 SQL 执行计划不能复用,因为 SQL 文本在常量参数化之后形式也是不一样的。

3 个赞

都是item_id上的OR,为啥不写成item_id in()的方式?

你是说WHERE 后面的条件是以文本方式传入的?对于多个OR的情况,改写为IN的方式,并且IN值按递增或递减的方式书写,效率会高一点。如果对于这个SQL,你手工改写为IN的方式,看看性能是否有提升。

in里的值按递增或递减的方式真的能提高效率吗,我之前理解随机和递增一样,希望大佬解答下。

1 个赞

我理解也是递增和随机一样,如果是唯一索引的话可能会不一样吧,按顺序能减少每个值的检索范围,不过感觉差别不会很大

1 个赞

此话题已在最后回复的 1 分钟后被自动关闭。不再允许新回复。