Left join和mysql执行结果不一致

  • 系统版本 & kernel 版本
    centos 7.6

  • TiDB 版本
    2.1.16

  • 集群节点分布
    pd节点:10.128.3.55/56/57
    db节点:10.128.3.55/56/57
    kv节点:10.128.3.55/56/57

  • 问题描述(我做了什么)
    周四将tidb从2.1.5升级到了2.1.16,bi人员反馈数据有问题,发现同样的SQL在MySQL5.7.18和tidb2.1.16上执行的结果不一致
    SQL:
    SELECT COUNT(*)
    FROM users t1
    LEFT JOIN shuttle_bus.sys_city t2 ON t1.city_id=t2.id AND t2.level=2
    LEFT JOIN (SELECT user_id,MIN(CAST(pay_time AS DATE)) first_pay_time
    FROM shuttle_bus.orders WHERE pay_status=‘1’ GROUP BY user_id
    ) t3 ON t1.id=t3.user_id
    WHERE 1=1
    AND t1.city_id=‘10024’
    AND CAST(t1.ctime AS DATE)>=‘2019-07-29’
    AND CAST(t1.ctime AS DATE)<‘2019-08-28’
    MySQL上执行的结果为120条
    tidb上执行的结果为19条
    执行计划

请问 TiDB 和 MySQL 的这几个表 t1 t2 t3 的数据一样吗

是一样的,通过otter实时的从mysql同步到tidb

麻烦去 MySQL 和 TiDB 中分别查一下以下 SQL 比对下结果:

select count(*) from users t1 where t1.city_id=‘10024’ AND CAST(t1.ctime AS DATE)>=‘2019-07-29’ AND CAST(t1.ctime AS DATE)<‘2019-08-28’;

select count(*) from shuttle_bus.sys_city t2 where t2.level=2;

SELECT count(*) FROM shuttle_bus.orders WHERE pay_status=‘1’ GROUP BY user_id;

是一样的,结果分别是120,14,下面那条sql不加group by的结果是345828

方便提供一下表结构吗 如果可以的话: http://${tidb-server-ip}:${tidb-server-status-port}/stats/dump/${db_name}/${table_name} 把统计信息也导出来上传一下。

好的,表结构和统计信息我上传了,这个问题有点急,麻烦老师了!

我在测试环境装上了2.1.6版本,发现SQL执行结果和MySQL一致,可以确定是版本的问题啊!2.1.16可以回退到2.1.6吗?

稍等,我们研发同学正在确认。 目前没有通过标准方法回退,只能导出导入方式。 您把 2.1.6 的执行计划发一下

这是在2.1.6上的执行计划

麻烦把 SQL 改一下: 将 “CAST(t1.ctime AS DATE)>=‘2019-07-29’ AND CAST(t1.ctime AS DATE)<‘2019-08-28’” 去掉 CAST 改成 “t1.ctime>=‘2019-07-29’ AND t1.ctime<‘2019-08-28’ ”

改好后跑一次,反馈给我结果

执行结果一致了

我们后续会修复这个问题,所以现在麻烦先用这个 SQL 。

老师,这是是什么原因呢?是因为多left join和cast有冲突还是仅仅是多left join的问题啊?

多谢老师,我们还有其他的多left join的SQL,现在还不能确定是否其他的SQL还有影响!

cast 让优化器误把 left join 转成了 inner join ,可以看看其他 left join 的 SQL 中有没有包含 cast 如果那些字段本来就是 date 类型的话,其实也不用使用 cast 转换格式了。

明白,谢谢老师!

如果觉得别人的回答有帮助,可以将其标记为解决方案✅,这样其他有同样问题的人也可以快速找到答案~

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