一个join条件造成的1000倍的性能差距

以上两个方法都试了,不行,还是慢,没效果。

去掉这个left join 很快?不会是有笛卡尔积吧。

上面我回答的不对,是去掉dp.TYPE=‘MARK_TYPE’这个就会很快

加了hint以后连接顺序对吗?
如果不对,SHOW WARNINGS;显示什么?

这样会快么?

LEFT JOIN (SLECT * FROM dict_private_data WHERE TYPE = 'MARK_TYPE') dp on dp.HOSP_ID = mm.HOSPITAL_ID AND dp.PRIVATE_ID = mm.MARK_TYPE

这样没有快,还是一样

执行这个后是空

1 个赞

执行计划有吗?没警告应该是生效的。我想知道连接顺序是否有变化。

a388d21d58139ec1f4e736d6a9662b1e64d586226519906946d0b959e90e0560.txt (99.6 KB)
这个是加hint后的

1 个赞

和我想象的连接顺序不一样,也可能是我对这个hint的理解有问题。

总之这个查询之所以低效就是因为dp和mm之间用的是hashjoin而不是indexjoin,然后mm有400w数据然后就慢了。
而好的执行计划是因为对mm的过滤性非常好,只需要精准的利用索引找几条所以就快1000倍。

from biz_patient_med_mapping mm
LEFT JOIN dict_private_data dp on dp.HOSP_ID=mm.HOSPITAL_ID and dp.PRIVATE_ID = mm.MARK_TYPE and dp.TYPE=‘MARK_TYPE’
where mm.ENABLE =1 and mm.IS_DEFAULT = 1

聚焦一下问题,其实就是上面这个sql,在什么索引的情况下可以走indexjoin。或者mm在where中添加什么条件,可以显著缩小mm的结果集。
这两个条件只要能做到一个,应该都会有比较明显的提升。

在之前版本IndexJoin的innerSide不支持非DataSource的算子,这个在8.1版本修改了,新增了对Agg算子的支持,但还不支持其它算子(比如各种Join)。
因此对于a join (b join c)形式目前是不支持a indexJoin (b join c)的,可以支持(b join c) indexJoin a。
也就是join的innerSide不能是(b join c)。
可参考这里:指定INL_JOIN,但执行计划并不走
你用的8.1版本只支持了innerSide是Datasource和Agg算子,join类的还不支持:https://github.com/pingcap/tidb/issues/37068

根据这种理解看是否能找到正确答案。

1 个赞

简单的时间对比不好分析原因,最好的办法还是分析执行计划。
jion效率低往往几方面:
1,一般的建议是join表不要超过3个。
2,驱动表很重要,执行计划驱动表有没有搞对。
3,join可以走索引的,关联字段加索引能有效加速。不走可能因为没建或者统计数据不对。

对比了你这两个执行计划,看着是优化器选择的关联顺序有问题,你可以通过Hints指定下表关联的顺序,让p、mm和im表先关联,然后最后再与dp表关联,避免p表和dp表先进行关联

Join顺序的不同,执行计划的差异有时候是巨大的,我们之前就吃过不少这个亏,我们是V6.5版本,在较多表关联的场景下说实话TiDB优化器走偏还是有不小概率发生,不知道现在高版本优化器提升有多少。

1 个赞

优化器不同了

为什么会优化器不同,请问有方法解决吗?

继续,不要沉,有没有官方解答下

需要一些更详细的信息, 可以通过plan replayer 收集一下 explain analyze 的执行计划

没仔细看。走tiflash试试。