左右连接 #
原理 #
DBPlusEngine 目前支持绑定表、广播表和单表的左右连接查询,在进行绑定表左右连接查询时,需要在连接条件中指定分片键。分片表和广播表,分片表和单表的连接查询暂不支持,需要依赖 SQL Federation 引擎提供查询能力。
关系表如下所示:
组合 | 关联条件 | 是否支持 | 处理引擎 |
---|---|---|---|
分片表+分片表 | 分片键+绑定 | 是 | 内核 |
分片键+非绑定 | 是 | 实验性 SQL Federation 引擎,需要手动开启 | |
非分片键 | 是 | 实验性 SQL Federation 引擎,需要手动开启 | |
分片表+单表 | 分片键 | 是 | 实验性 SQL Federation 引擎,需要手动开启 |
非分片键 | 是 | 实验性 SQL Federation 引擎,需要手动开启 | |
分片+广播表 | 分片键 | 否 | 内核(存在 bug,左右连接数据重复,支持内连接) |
非分片键 | 否 | 内核(存在 bug,左右连接数据重复,支持内连接) | |
单表+广播表 | 不限制 | 是 | 内核 |
单表+单表 | 不限制 | 是 | 内核(同库场景) |
不限制 | 是 | 实验性 SQL Federation 引擎,需要手动开启(跨库场景) |
DBPlusEngine 在执行绑定表的连接查询时,会选择指定了分片条件的表作为主表进行路由改写,其他绑定表根据绑定关系进行改写,然后将改写后的真实 SQL 下推到数据库执行,由于绑定表具有相同的数据分布,并且在查询时指定了分片键作为关联条件,因此原生数据库的关联查询结果可以作为逻辑 SQL 的查询结果,最后通过归并引擎对多个分片的结果进行合并。
而在执行广播表和单表的连接查询时,DBPlusEngine 会以单表为主表进行路由,然后将 SQL 下推到数据库执行,得到关联查询的结果。
建议 #
- 将多个具有相同分片规则的表配置为绑定表,以保证可以将关联查询下推至数据库执行。
示例 #
如下示例展示了 DBPlusEngine 支持的关联查询,t_order 和 t_order_item 为绑定表,t_config 为广播表,t_single 为单表。
-- 查询各个表的数据
mysql> select * from t_order;
+----------+---------+---------+
| order_id | user_id | content |
+----------+---------+---------+
| 2 | 2 | TEST2 |
| 4 | 1 | test11 |
| 1 | 1 | %TEST1 |
| 3 | 3 | test3 |
| 5 | 1 | test11 |
+----------+---------+---------+
5 rows in set (0.01 sec)
mysql> select * from t_order_item;
+---------+----------+---------+---------+
| item_id | order_id | content | user_id |
+---------+----------+---------+---------+
| 2 | 2 | TEST2 | 2 |
| 1 | 1 | TEST1 | 1 |
+---------+----------+---------+---------+
2 rows in set (0.01 sec)
mysql> SELECT * FROM t_config;
+-----------+---------+
| config_id | content |
+-----------+---------+
| 1 | TEST1 |
| 2 | TEST2 |
| 3 | TEST3 |
| 4 | TEST4 |
+-----------+---------+
4 rows in set (0.00 sec)
mysql> SELECT * FROM t_single;
+-----------+---------+
| single_id | content |
+-----------+---------+
| 1 | TEST1 |
| 2 | TEST2 |
+-----------+---------+
2 rows in set (0.01 sec)
-- 绑定表左连接
mysql> select * from t_order o left join t_order_item i on o.order_id = i.order_id and o.user_id = i.user_id;
+----------+---------+---------+---------+----------+---------+---------+
| order_id | user_id | content | item_id | order_id | content | user_id |
+----------+---------+---------+---------+----------+---------+---------+
| 2 | 2 | TEST2 | 2 | 2 | TEST2 | 2 |
| 4 | 1 | test11 | NULL | NULL | NULL | NULL |
| 1 | 1 | %TEST1 | 1 | 1 | TEST1 | 1 |
| 3 | 3 | test3 | NULL | NULL | NULL | NULL |
| 5 | 1 | test11 | NULL | NULL | NULL | NULL |
+----------+---------+---------+---------+----------+---------+---------+
5 rows in set (0.01 sec)
-- 绑定表右连接
mysql> select * from t_order o right join t_order_item i on o.order_id = i.order_id and o.user_id = i.user_id;
+----------+---------+---------+---------+----------+---------+---------+
| order_id | user_id | content | item_id | order_id | content | user_id |
+----------+---------+---------+---------+----------+---------+---------+
| 2 | 2 | TEST2 | 2 | 2 | TEST2 | 2 |
| 1 | 1 | %TEST1 | 1 | 1 | TEST1 | 1 |
+----------+---------+---------+---------+----------+---------+---------+
2 rows in set (0.01 sec)
-- 广播表、单表左连接
mysql> SELECT * FROM t_config o LEFT JOIN t_single s ON o.config_id = s.single_id;
+-----------+---------+-----------+---------+
| config_id | content | single_id | content |
+-----------+---------+-----------+---------+
| 1 | TEST1 | 1 | TEST1 |
| 2 | TEST2 | 2 | TEST2 |
| 3 | TEST3 | NULL | NULL |
| 4 | TEST4 | NULL | NULL |
+-----------+---------+-----------+---------+
4 rows in set (0.00 sec)
-- 广播表、单表右连接
mysql> SELECT * FROM t_config o RIGHT JOIN t_single s ON o.config_id = s.single_id;
+-----------+---------+-----------+---------+
| config_id | content | single_id | content |
+-----------+---------+-----------+---------+
| 1 | TEST1 | 1 | TEST1 |
| 2 | TEST2 | 2 | TEST2 |
+-----------+---------+-----------+---------+
2 rows in set (0.00 sec)