tidb优化器是这么啦?

单表sql查询,优化器都选错执行计划


有索引,不走,反而走全表扫

请问大佬们,这个问题如何解决(先不用hospital_id、created_at列的联合索引),为什么不选择created_at列索引?

1 个赞

改sql
SELECT COUNT(*) FROM t_registering_orders USE INDEX(idx_tro_createdat)
WHERE hospital_id = 1739
AND created_at >= ‘2026-08-04 00:00:00’
AND created_at < ‘2026-09-03 00:00:00’;

1 个赞

只能强制hint了。和数据库没关系。看直方图的评估吧。


analyze table后的执行计划

就是不选择索引

1 个赞


指定索引提升一倍的性能

1 个赞

你这走索引数据量也大,还不如走全表扫描了


两千三百多万记录,过滤100万,不到5%的记录?

1 个赞

全表扫描 顺序读 2300 万行(单行成本很低)
走索引 顺序读 103 万索引项 + 随机回表 103 万行(单次成本很高)

1 个赞

为什么指定索引,查询时间确实快很多

优化器考虑的不是查询时间,是资源消耗

优化器是要考虑资源,没错,但查询出结果时间很长,应用接受不了,没意义

优化器可能任务100W的数据回表产生的消耗更大。而且看执行计划的时间,full 是1s, index是3秒吧,而且index 占用的内存还多。
但是没找到是否有相关的参数可以限制比例之类的。

优化器的逻辑就是这样没办法,
正常就应该有个组合索引 就没这个问题了

1 个赞

看下统计信息是不是不准,先跑下 ANALYZE TABLE 表名 刷新下。如果还不行,试试用 FORCE INDEX(created_at) 强制走索引验证下效果。另外检查下查询条件里对 created_at 有没有函数操作或隐式转换,比如 DATE(created_at) 或字符串比较,会导致索引失效。如果数据分布倾斜,优化器预估扫描行数少也可能选错,可以调下 tidb_opt_scan_choose 或直接 hint。

1 个赞

执行计划里写的 stats:pseudo 表示 TiDB 用的不是 “偏差的统计”,而是伪统计—— 也就是统计信息缺失、没加载或过期到失效,收集下统计信息看一下

1 个赞

如果只是统计数量,而且hospital_id、created_at 字段不为空,可以考虑直接count(hospital_id),通过 ‌Index Merge避免回表。

搞个组合索引会比较好,或者绑定执行计划

弄个组合索引试试