关联子查询去关联
以 为例,这里子查询 t1.a < (select sum(t2.a) from t2 where t2.b = t1.b)
中涉及了关联列上的条件 t2.b=t1.b
,不过恰好由于这是一个等值条件,因此可以将其等价的改写为 select t1.* from t1, (select b, sum(a) sum_a from t2 group by b) t2 where t1.b = t2.b and t1.a < t2.sum_a;
。这样,一个关联子查询就被重新改写为 的形式。
这种改写的弊端在于,在关联没有被解除时,优化器是可以使用关联列上的索引的。也就是说,虽然这个子查询可能被重复执行多次,但是每次都可以使用索引过滤数据。而解除关联的变换上,通常是会导致关联列的位置发生改变而导致虽然子查询只被执行了一次,但是单次执行的时间会比没有解除关联时的单次执行时间长。
上面是优化生效的情况,可以看到 HashJoin_11
是一个普通的 inner join
。
在执行了关闭关联规则的语句后,可以在 IndexRangeScan_25(Build)
的 中看到 range: decided by [eq(test.t2.b, test.t1.b)]
。这部分信息就是关联依赖未被解除时,TiDB 使用关联条件进行索引范围查询的显示结果。