多表关联时,通过explain查看执行计划,查看SQL语句是否使用到分布键(前面已介绍),查看SQL关联是否使用到了分布键。
如果两表关联都使用到了分布键,那么两表关联可以在dn节点内完成,不需要在dn节点之间交互数据;如果其中一张表没有用分布键,那么两表关联不能在dn节点内完成,该表需要在dn节点之间交互数据;如果两张表都没有使用分布键,那么两张表都需要在dn节点之间交互数据。
两表关联时,应优先使用两表的分布键关联,尽量保证高频并发的SQL都用到了分布键关联;其次至少有一张表用到了分布键,也可以减少一次数据重分布;两张表都没有用到分布键的场景应尽量避免。同时,两表关联时如果只能有一个表带分布键,那么更大的表、或查询结果集更大的表优先使用到分布键,让小一点的表去重分布数据。
在执行计划中,如果DN之间有数据重分布,那么执行计划中会有这样的关键字Distribute results by S: f1,这里表示按f1进行数据重分布。
例如,teledb_1的分布键为f2,teledb_2的分布键为f1,下面的SQL,两表关联时teledb_1没有用到分布键,两表关联不能在dn节点内完成,需要dn节点之间发起数据交互(重分布),teledb_1在完成表扫描后发起了按f1字段重分布的动作,对应执行计划中的Distribute results by S: f1。
teledb=# explain select teledb_1.* from teledb_1,teledb_2 where teledb_1.f1=teledb_2.f1 ;
QUERY PLAN
------------------------------------------------------------------------------------------------
Remote Subquery Scan on all (dn001,dn002) (cost=29.80..186.32 rows=3872 width=40)
-> Hash Join (cost=29.80..186.32 rows=3872 width=40)
Hash Cond: (teledb_1.f1 = teledb_2.f1)
-> Remote Subquery Scan on all (dn001,dn002) (cost=100.00..158.40 rows=880 width=40)
Distribute results by S: f1
-> Seq Scan on teledb_1 (cost=0.00..18.80 rows=880 width=40)
-> Hash (cost=18.80..18.80 rows=880 width=4)
-> Seq Scan on teledb_2 (cost=0.00..18.80 rows=880 width=4)
(8 rows)
例如下面的SQL,teledb_1和teledb_2关联时都用到了分布键,那么两表关联可以在dn节点内完成,不需要在dn节点之间交互数据。
teledb=# explain select teledb_1.* from teledb_1,teledb_2 where teledb_1.f2=teledb_2.f1 ;
QUERY PLAN
---------------------------------------------------------------------------------
Remote Fast Query Execution (cost=0.00..0.00 rows=0 width=0)
Node/s: dn001, dn002
-> Hash Join (cost=18904.69..46257.08 rows=500564 width=14)
Hash Cond: (teledb_1.f2 = teledb_2.f1)
-> Seq Scan on teledb_1 (cost=0.00..9225.64 rows=500564 width=14)
-> Hash (cost=9225.64..9225.64 rows=500564 width=4)
-> Seq Scan on teledb_2 (cost=0.00..9225.64 rows=500564 width=4)
(7 rows)