在实际的业务场景中,多个表的Join语句是很常见的,而Join的执行效率和各个表参与Join的顺序有关系。如select*fromt1,t2,t3wheret1.a=t2.aandt3.a=t2.a,这个SQL中可能的执行顺序有“t1和t2先做Join,然后再和t3做Join”以及“t2和t3先做Join,然后再和t1做Join”两种情况。根据t1和t3的数据量及数据分布,这两种执行顺序会有不同的性能表现。
因此优化器需要实现一种决定Join顺序的算法。目前TiDB中存在两种JoinReorder算法,贪心算法和动态规划算法。
JoinReorder贪心算法实例以三个表t1、t2、t3的Join为例。首先获取所有参与Join的节点,将所有节点按照行数多少,从少到多进行排序。
之后选定其中最小的表,将其与其他两个表分别做一次Join,观察输出的结果集大小,选择其中结果更小的一对。
然后进入下一轮的选择,如果这时是四个表,那么就继续比较输出结果集的大小,进行选择。这里只有三个表,因此就直接得到了最终的Join结果。
JoinReorder动态规划算法实例仍然以上述例子为例。动态规划算法会枚举所有的可能性,因此相对贪心算法必须从t1表开始枚举,动态规划算法可以枚举如下的Join顺序。
当该选择比贪心算法更优时,动态规划算法便可以选择到更优的Join顺序。
JoinReorder算法的控制目前JoinReorder算法由变量tidb_opt_join_reorder_threshold控制,当参与JoinReorder的节点个数大于该阈值时选择贪心算法,反之选择动态规划算法。
JoinReorder算法限制当前的JoinReorder算法存在如下限制:
目前TiDB中支持使用STRAIGHT_JOIN语法来强制指定一种Join顺序,参见语法元素说明。