最近在做数据库迁移验证,发现有个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如下,供参考: