请教TiDB多表关联时是怎么实现下推的?

Greenplum之类分布式数据库的表关联,关联键和分布键不相同的时候,有重分布和广播的概念。
TiDB在关联多个表的时候可以将关联下推到TiKV节点执行吗,具体怎么实现的呢?

总体思路是在执行计划优化阶段会先将多表转为多组2个表的关联查询,2个表的关联查询再转换为对单表的查询,然后在存储层对单表进行过滤和读取数据,再回到计算层对数据进行联合查询,具体不同的联合查询join算子再走对应的计算和读取数据过程。

1 个赞

表分片后在,各个分片的数据在各自的节点上计算,减少tidb节点的计算压力,tidb节点负责汇总计算

我的理解,tidb关联时不会把关联下推到tikv节点,只会对谓词进行下推,以期每个tikv节点能尽量少的返回数据,减少传输量,但是不会直接将两个表的关联下推到tikv节点而只返回关联出的数据。

2 个赞

join 不能下推到 tikv,TiFlash 支持 join 下推。可以加一个 TiFlash 节点,并且相关表都加上 TiFlash 副本。

大佬,有相关的资料吗

请看官方文档中关于TopN和Limit下推的情况
TopN 和 Limit 下推 | PingCAP 文档中心

示例 2:TopN 下推过 Join 的情况(排序规则仅依赖于外表中的列)

create table t(id int primary key, a int not null);
create table s(id int primary key, a int not null);
explain select * from t left join s on t.a = s.a order by t.a limit 10;
+----------------------------------+----------+-----------+---------------+-------------------------------------------------+
| id                               | estRows  | task      | access object | operator info                                   |
+----------------------------------+----------+-----------+---------------+-------------------------------------------------+
| TopN_12                          | 10.00    | root      |               | test.t.a, offset:0, count:10                    |
| └─HashJoin_17                    | 12.50    | root      |               | left outer join, equal:[eq(test.t.a, test.s.a)] |
|   ├─TopN_18(Build)               | 10.00    | root      |               | test.t.a, offset:0, count:10                    |
|   │ └─TableReader_26             | 10.00    | root      |               | data:TopN_25                                    |
|   │   └─TopN_25                  | 10.00    | cop[tikv] |               | test.t.a, offset:0, count:10                    |
|   │     └─TableFullScan_24       | 10000.00 | cop[tikv] | table:t       | keep order:false, stats:pseudo                  |
|   └─TableReader_30(Probe)        | 10000.00 | root      |               | data:TableFullScan_29                           |
|     └─TableFullScan_29           | 10000.00 | cop[tikv] | table:s       | keep order:false, stats:pseudo                  |
+----------------------------------+----------+-----------+---------------+-------------------------------------------------+
8 rows in set (0.01 sec)

在该查询中,TopN 算子的排序规则仅依赖于外表 t 中的列,可以将 TopN 下推到 Join 之前进行一次计算,以减少 Join 时的计算开销。除此之外,TiDB 同样将 TopN 下推到了存储层中。

示例 4:TopN 转换成 Limit 的情况

create table t(id int primary key, a int not null);
create table s(id int primary key, a int not null);
explain select * from t left join s on t.a = s.a order by t.id limit 10;
+----------------------------------+----------+-----------+---------------+-------------------------------------------------+
| id                               | estRows  | task      | access object | operator info                                   |
+----------------------------------+----------+-----------+---------------+-------------------------------------------------+
| TopN_12                          | 10.00    | root      |               | test.t.id, offset:0, count:10                   |
| └─HashJoin_17                    | 12.50    | root      |               | left outer join, equal:[eq(test.t.a, test.s.a)] |
|   ├─Limit_21(Build)              | 10.00    | root      |               | offset:0, count:10                              |
|   │ └─TableReader_31             | 10.00    | root      |               | data:Limit_30                                   |
|   │   └─Limit_30                 | 10.00    | cop[tikv] |               | offset:0, count:10                              |
|   │     └─TableFullScan_29       | 10.00    | cop[tikv] | table:t       | keep order:true, stats:pseudo                   |
|   └─TableReader_35(Probe)        | 10000.00 | root      |               | data:TableFullScan_34                           |
|     └─TableFullScan_34           | 10000.00 | cop[tikv] | table:s       | keep order:false, stats:pseudo                  |
+----------------------------------+----------+-----------+---------------+-------------------------------------------------+
8 rows in set (0.00 sec)

在上面的查询中,TopN 首先推到了外表 t 上。然后因为它要对 t.id 进行排序,而 t.id 是表 t 的主键,可以直接按顺序读出 (keep order:true),从而省略了 TopN 中的排序,将其简化为 Limit。

1 个赞

TiDB数据库在走TiKV时,不能像你说的将JOIN下推到TiKV去执行,顶多是把各种条件下推下去,增加执行效率,JOIN的算子执行还是在TiDB Server计算层做的,可参考官方文档优化章节理解算子执行:https://docs.pingcap.com/zh/tidb/stable/explain-overview#tidb-执行计划概览

当走TiFlash存储引擎时,可以使用MPP模式执行,这样就能让Tiflash做JOIN,就能使用Broadcast Hash Join、Shuffled Hash Join、 Shuffled Hash Aggregation等算子了,这就涉及到你说的数据重分布、广播等操作了,参考:
https://docs.pingcap.com/zh/tidb/stable/use-tiflash-mpp-mode#使用-mpp-模式

1 个赞

下推的前提是使用分片健进行关联查询

和我预想的一致,TiDB的region分片不是按hash来的,也无复制表的概念,所以是不能下推关联的。
感谢各位解惑🙏

刚看了下 Runtime Filter,设计很巧妙 :+1:

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