1 问题
在实际工作中,经常会遇到多张表进行 join 查询的操作,例如 orders 表被我们做了水平拆分,表中记录分散存储在两个数据分片中,但是 order_details 表并没有做分片,因此在对这两张表做 join 查询时,数据库1仅能在分片后的数据中进行查询,数据库2因为没有找到 order_details 表而返回空,那么整个查询结果将是实际结果的一个子集。
mycat中的join查询结果
创建 order_details 表并使用join进行查询
create table order_details(id int auto_increment primary key,order_id int, detail varchar(200));
数据库1中的记录
数据库2中的记录
那么为了解决这个问题,引入了ER表。
2 ER表
ER表是为了解决跨分片进行表的关联查询的,有关联关系的表放到一个分片里,没关联关系的随意。
子表的存储位置将依赖于父表,并且在物理上紧邻存放,根据这个思路,采用基于E-R关系的数据分片策略,这样就解决了在数据分片时,join查询遇到的问题。
例如,customer 表中的数据,当与父表 orders 数据存在关联时,该部分数据将被分配到同一个分片里,以方便进行关联操作。
3 实现
3.1 修改 schema.xml 配置
在 table 节点下,增加 childTable 子节点。
增加的内容如下:
<childTable name="order_details" primaryKey="id" joinKey="order_id" parentKey="id"/>
- name 要table关联的子表表名;
- primaryKey 子表的主键;
- joinKey 做join连接查询的列名;
- parentKey 用于join连接查询的列在父表中对应的列名
添加后,效果如下
3.2 重启mycat
修改配置后,重新启动mycat服务
mycat restart
3.3 在数据库2创建子表
此时,在mycat中进行join查询时,会报错
mysql> select * from orders as o left JOIN order_details as od on od.order_id=o.id;
ERROR 1146 (42S02): Table 'orders.order_details' doesn't exist
因为在数据库2中并不存在 order_details 表。
因此,需要先在数据库2中创建 order_details 表。
3.4 在mycat中重新查询
进入到mycat数据端口,重新执行1中的查询。
所有记录都能被查询出来。
3.5 插入数据
向 order_details 表中插入几条记录
insert into order_details(detail, order_id) values("details001", 1);
insert into order_details(detail, order_id) values("details002", 2);
insert into order_details(detail, order_id) values("details003", 3);
需要注意的是:
这里向子表中插入数据时,用来进行关联的列的值,应在父表中存在对应的数据,否则会遇到报错
ERROR 1064 (HY000): can't find (root) parent sharding node for sql
3.6 数据查询
分别进入各数据库分片进行查询,可以发现子表中,与父表关联的数据,被存储于同一个数据库分片中。
数据库分片1
数据库分片2
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!