dashboard 执行计划与实际执行计划不一致

这个是dashboard 的执行计划 image
这个是我在后台实际执行的


sql语句应该是走索引才对的,后台执行也是对的,走的是索引。但是dashboard的慢日志查询出来的执行计划,b表还是一直走全表。请问这个是dashboard取的有问题吗?

dashbaord 中看到的 执行计划其实是 真实的 执行计划
同时 tidb 的 执行计划生成是同时基于规则与代价的 。相同的 sql 入参不同也会有不同的 执行计划。并且随着 统计信息的迭代更新,执行计划也会发生变化。

为了解决 执行计划不稳定这个问题 官方也提供了 SPM 这样的管理工具,让用户可以手动管理 sql 的 执行计划

https://docs.pingcap.com/zh/tidb/stable/control-execution-plan

感谢您的回复,如果dashbaord是真实的执行计划,为什么相同的sql,执行计划不一样呢?

这个是dashboard的执行计划, 这个是后台的执行计划。这个有点想不通啊。现在根据dashboard去优化慢查询,发现这个慢sql在后台查询很快,但是2个执行计划不一致。

上面的回复其实也有点到 tidb 的 执行计划生成是基于代价与 规则的
基于代价生成执行计划,就和统计信息分不开。统计信息是在达到特定阈值后会自动收集的。
所以统计信息收集的前后,执行计划不一样也是有可能的。

相关资料可以查阅

慢语句相关章节

感谢你的回答,我的意思是我的统计信息都是刚刚收集,都是准确的。表的健康度也是100%的。我手动执行的sql也是最理想的执行计划,但是程序端,连接之后,执行同样的sql,就拉入了慢日志。并且从dashboard的执行计划上面看,和我手动执行的实际的执行计划不一致。难道手动执行和程序连接执行的计划不一样吗?

因为这个sql程序是不断的调用的,一直都是一样的执行计划。

具体会有这种情况的根因不好断言
可能和 统计信息缓存有关。也可能和程序连接的 排序规则有关。

不过我们可以先使用 SPM 将执行计划进行下绑定
使用 sql hint 强制 这个 SQL 走指定的索引

https://docs.pingcap.com/zh/tidb/stable/control-execution-plan

可以提供下这个 SQL 的文本和对应两个表的表结构吗?另外这是什么版本的 TiDB?

谢谢,是我没写清楚,tidb的版本是:v4.0.9 这个是sql的文本

这个是添加强制让他走索引,但是还是没有达到在后台执行的实际效果,他的执行计划是

后台执行的最优的计划

对应的表结构以及索引

image

我通过去绑定这个后台执行的执行计划也不行,绑了之后,sql执行的还是原计划。就是无法触发
| ├─Point_Get_11(Build) | 1.00 | root | table:ims_user_balance, index:PRIMARY(user_id) |
| └─Point_Get_10(Probe) | 1.00 | root | table:ims_user, index:user_id_index(user_id) |
这个

在这里也可以看出来,还是体现以前的表,这个sql是经过改写的,变为2个表的,这里还有显示出以前的表在里面。很奇怪。

image 执行计划缓存是关闭的。

统计信息和表的健康度都是好的。

可以贴文字吗,这样方便复现些 :joy:

-------------表结构------------
CREATE TABLE ims_user (
id int(11) NOT NULL AUTO_INCREMENT,
user_id char(15) COLLATE utf8mb4_general_ci NOT NULL COMMENT ‘用户名’,
parent_user_id varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘父级的user_id’,
level_id int(11) NOT NULL DEFAULT ‘1’ COMMENT ‘层级Id’,
user_level_lock tinyint(4) DEFAULT ‘0’ COMMENT ‘层级锁定标识 0 解锁 1锁定’,
nick_name varchar(50) COLLATE utf8mb4_general_ci DEFAULT ‘’ COMMENT ‘用户别名’,
user_flag varchar(50) COLLATE utf8mb4_general_ci NOT NULL DEFAULT ‘’ COMMENT ‘用户标识’,
safety_box_passwd varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘保险箱密码’,
password varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘用户密码’,
salt varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘密码盐’,
phone varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘手机号’,
real_name varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘真实姓名’,
image_url varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘头像’,
is_test_online tinyint(1) DEFAULT ‘0’ COMMENT ‘是否测试线: 0:正常用户 ,1:测试用户’,
email varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘邮箱’,
sex tinyint(1) DEFAULT NULL COMMENT ‘性别 0 男 1 女’,
birthday varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘生日’,
status tinyint(1) DEFAULT ‘0’ COMMENT ‘状态0启动1为禁用,2:冻结’,
login_ip varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘最后一次登入IP’,
register_ip varchar(20) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘注册ip’,
qq varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘qq号’,
wechat varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘微信’,
last_login_date datetime DEFAULT NULL COMMENT ‘最后一次登录时间’,
channel_flag bigint(20) DEFAULT NULL,
channel_flag_sub varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘平台渠道代理标识子级’,
device_flag varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘用户设备标识’,
device_type tinyint(1) DEFAULT NULL COMMENT ‘1:andoid 2:ios 3:andoid h5 4. ios h5 5:pc’,
swich_status varchar(1) COLLATE utf8mb4_general_ci DEFAULT ‘1’ COMMENT ‘0 手动 1自动’,
update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘创建时间’,
remark varchar(150) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘备注’,
bank_passwd varchar(100) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘提现密码’,
version int(11) DEFAULT ‘0’ COMMENT ‘版本’,
vip_id int(11) DEFAULT NULL COMMENT ‘关联vip字段’,
vip_exp bigint(20) DEFAULT ‘0’ COMMENT ‘用户经验值’,
sub_amount int(11) DEFAULT ‘0’ COMMENT ‘下级数量’,
PRIMARY KEY (id),
KEY create_time_index (create_time),
KEY update_time_index (update_time),
KEY level_id_index (level_id),
KEY channel_flag_index (channel_flag),
UNIQUE KEY user_id_index (user_id),
KEY user_flag_index (user_flag),
KEY phone_index (phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci AUTO_INCREMENT=1056808 COMMENT=‘会员表’;

CREATE TABLE ims_user_balance (
user_id varchar(50) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
total_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘用户余额’,
freeze_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘冻结金额’,
current_dml decimal(18,2) DEFAULT ‘0.00’ COMMENT ‘当前打码量’,
chuk_dml decimal(18,2) DEFAULT ‘0.00’ COMMENT ‘出款要求打码量’,
safety_box_balance decimal(18,2) DEFAULT ‘0.00’ COMMENT ‘保险箱余额’,
count_in_times int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘累计入款次数’,
count_in_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘累计入款总额’,
count_out_times int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘累计出款次数’,
count_out_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘累计出款金额’,
count_dml decimal(18,2) DEFAULT ‘0.00’ COMMENT ‘已达打码量累计’,
count_touzhu_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘投注总额’,
count_valid_touzhu_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘有效投注总额’,
count_zhjiang_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘中奖总额’,
count_huodong_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘活动总额’,
count_fanshui_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘反水金额’,
count_fanyong_money decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘返佣金额’,
first_deposit_money decimal(18,2) DEFAULT ‘0.00’ COMMENT ‘首冲金额’,
second_deposit_money decimal(18,2) DEFAULT ‘0.00’ COMMENT ‘二充金额’,
exp decimal(18,2) NOT NULL DEFAULT ‘0.00’ COMMENT ‘经验值’,
create_time datetime DEFAULT NULL,
update_time datetime DEFAULT NULL,
create_by varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘创建人’,
update_by varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT ‘更新人’,
single_max_in_money decimal(18,2) NOT NULL DEFAULT ‘0.00’,
PRIMARY KEY (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT=‘用户余额表’ ;

---------sql语句:---------
SELECT
u.user_id,
u.level_id,
u.user_level_lock,
u.parent_user_id AS parentUserId,
u.real_name,
u.image_url,
u.status,
u.swich_status,
u.login_ip,
u.register_ip,
u.last_login_date,
u.create_time,
u.phone,
u.email,
u.qq,
u.birthday,
u.nick_name,
u.is_test_online,
u.remark,
u.safety_box_passwd,
u.vip_id,
u.channel_flag,
u.channel_flag_sub,
u.bank_passwd,
u.user_flag,
u.device_type,
u.vip_exp,
iub.count_in_money,
iub.count_out_money,
iub.total_money,
iub.freeze_money,
iub.current_dml,
iub.chuk_dml,
iub.count_valid_touzhu_money
FROM
ims_user u
JOIN ims_user_balance iub ON u.user_id = iub.user_id
WHERE
u.user_id = ‘zm123456’;

你的 关联建 发生了隐式转换 user_id。请问你后台测试时候 是否是这样的 语句。?

如果可以 请将对应表的统计信息导出下。以便更好的的确认问题

ims_user.json (52 字节) ims_user_balance.json (3.0 MB)