Greenplum之类分布式数据库的表关联,关联键和分布键不相同的时候,有重分布和广播的概念。
TiDB在关联多个表的时候可以将关联下推到TiKV节点执行吗,具体怎么实现的呢?
总体思路是在执行计划优化阶段会先将多表转为多组2个表的关联查询,2个表的关联查询再转换为对单表的查询,然后在存储层对单表进行过滤和读取数据,再回到计算层对数据进行联合查询,具体不同的联合查询join算子再走对应的计算和读取数据过程。
表分片后在,各个分片的数据在各自的节点上计算,减少tidb节点的计算压力,tidb节点负责汇总计算
我的理解,tidb关联时不会把关联下推到tikv节点,只会对谓词进行下推,以期每个tikv节点能尽量少的返回数据,减少传输量,但是不会直接将两个表的关联下推到tikv节点而只返回关联出的数据。
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。
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-模式
下推的前提是使用分片健进行关联查询
和我预想的一致,TiDB的region分片不是按hash来的,也无复制表的概念,所以是不能下推关联的。
感谢各位解惑🙏
刚看了下 Runtime Filter,设计很巧妙
此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。