not in subquery 执行计划不合理

最近在做数据库迁移验证,发现有个SQL在TiDB里跑崩了
简化后的SQL如下:
explain analyze
select * from global_ipm.project_plan_detail
where id not in (select project_plan_detail_id from global_ipm.project_plan_detail_task limit 100)
执行计划如下:


慢的原因是 join 的时候用了笛卡尔积算子
进一步研究,发现是因为project_plan_detail_id是一个可空字段(但实际上数据里没有空值),如果加个ifnull函数,就不会产生笛卡尔积:
explain analyze
select * from global_ipm.project_plan_detail
where id not in (select ifnull(project_plan_detail_id, 0) from global_ipm.project_plan_detail_task limit 100)

进一步研究发现,这是查询规划期间决定的,not in 碰到可空字段,主动选择了笛卡尔积的方式处理

我认为这不是一个很好的方式,数据量稍微大一点就会崩,完全可以处理的更加有效率

同样的SQL和数据,在impala里的执行的profile如下,供参考:

https://github.com/pingcap/tidb/issues/10226 肯看下这个

2019年就有人提issue了啊,现在还没改掉 :joy:

将 not in 改成 not exists 试一下。

1 个赞

not in里加个ifnull就可以解决的

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