5 绑定表
1 概念
指的是分片规则一致的关系表(主表、子表)
例如:
t_order和t_order_item,均按照order_id分片,则此两个表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,可以提升关联查询效率。
2 数据准备
分别创建t_course_section_0 和 t_course_section_1 表
CREATE TABLE `t_course_section_0` (
`id` bigint(11) NOT NULL,
`cid` bigint(11) DEFAULT NULL,
`corder_no` bigint(20) DEFAULT NULL,
`user_id` bigint(20) DEFAULT NULL,
`section_name` varchar(50) DEFAULT NULL,
`status` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `t_course_section_1` (
`id` bigint(11) NOT NULL,
`cid` bigint(11) DEFAULT NULL,
`corder_no` bigint(20) DEFAULT NULL,
`user_id` bigint(20) DEFAULT NULL,
`section_name` varchar(50) DEFAULT NULL,
`status` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
3 实体类
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;@Data
@ToString
@TableName("t_course_section")
public class CourseSection {private Long id;private Long cid;private Long userId;private Long corderNo;private String sectionName;private int status;
}
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.simon.entity.CourseSection;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface CourseSectionMapper extends BaseMapper<CourseSection> {
}
4 配置文件
# 应用名称
spring.application.name=sharding-jdbc
# 打印SQl
spring.shardingsphere.props.sql-show=true#===============数据源配置
#配置真实的数据源
spring.shardingsphere.datasource.names=db0,db1#数据源1
spring.shardingsphere.datasource.db0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db0.jdbc-url=jdbc:mysql://127.0.0.1:3306/course_db0?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.db0.username=root
spring.shardingsphere.datasource.db0.password=root#数据源1
spring.shardingsphere.datasource.db1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.db1.jdbc-url=jdbc:mysql://127.0.0.1:3306/course_db1?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root#1.配置数据节点 指定t_course逻辑表的真实分布情况
spring.shardingsphere.rules.sharding.tables.t_course.actual-data-nodes=db$->{0..1}.t_course_$->{0..1}
spring.shardingsphere.rules.sharding.tables.t_course_section.actual-data-nodes=db$->{0..1}.t_course_section_$->{0..1}#2.=========水平分库-分库策略========
# ---- t_course 分库策略
spring.shardingsphere.rules.sharding.tables.t_course.database-strategy.standard.sharding-column=user_id
# 分片算法名称:table-mod【自定义】
spring.shardingsphere.rules.sharding.tables.t_course.database-strategy.standard.sharding-algorithm-name=table-mod# ----t_course_section分库策略
spring.shardingsphere.rules.sharding.tables.t_course_section.database-strategy.standard.sharding-column=user_id
# 分片算法名称:table-mod【自定义】
spring.shardingsphere.rules.sharding.tables.t_course_section.database-strategy.standard.sharding-algorithm-name=table-mod#================水平分库-分表策略
# ---- t_course 分表策略
spring.shardingsphere.rules.sharding.tables.t_course.table-strategy.standard.sharding-column=corder_no
spring.shardingsphere.rules.sharding.tables.t_course.table-strategy.standard.sharding-algorithm-name=table-hash-mod# ---- t_course_section 分表策略
spring.shardingsphere.rules.sharding.tables.t_course_section.table-strategy.standard.sharding-column=corder_no
spring.shardingsphere.rules.sharding.tables.t_course_section.table-strategy.standard.sharding-algorithm-name=table-hash-mod#--分片算法
spring.shardingsphere.rules.sharding.sharding-algorithms.table-mod.type=MOD
# 2:取模的基数
spring.shardingsphere.rules.sharding.sharding-algorithms.table-mod.props.sharding-count=2spring.shardingsphere.rules.sharding.sharding-algorithms.table-hash-mod.type=HASH_MOD
spring.shardingsphere.rules.sharding.sharding-algorithms.table-hash-mod.props.sharding-count=2#---分布式主键
spring.shardingsphere.rules.sharding.tables.t_course.key-generate-strategy.column=cid
spring.shardingsphere.rules.sharding.tables.t_course.key-generate-strategy.key-generator-name=alg-snowflakespring.shardingsphere.rules.sharding.tables.t_course_section.key-generate-strategy.column=id
spring.shardingsphere.rules.sharding.tables.t_course_section.key-generate-strategy.key-generator-name=alg-snowflakespring.shardingsphere.rules.sharding.key-generators.alg-snowflake.type=SNOWFLAKE#======================绑定表
spring.shardingsphere.rules.sharding.binding-tables[0]=t_course,t_course_section
注意
binding-tables[0]此处是数组,意味着绑定表可以配置多个
5 测试
@Autowiredprivate CourseSectionMapper courseSectionMapper;@Testpublic void testInsertCourseAndCourseSection(){for (int i = 0; i < 3; i++) {Course course = new Course();course.setUserId(1L+i);course.setCname("绑定表" + i);course.setCorderNo(1000L+i);course.setBrief("绑定表");course.setPrice(100.00);course.setStatus(1);courseMapper.insert(course);Long cid = course.getCid();for (int j = 0; j < 30; j++) {CourseSection section = new CourseSection();section.setCid(cid);section.setUserId(1L+i);//corderNo是分表策略的分片键section.setCorderNo(1000L+i);section.setSectionName("绑定表_detail_" + i);section.setStatus(1);courseSectionMapper.insert(section);}}}
6 查看表结果
注意:
数据会入对应的主表和明细表,避免出现笛卡尔积,如图所示:
7 绑定表的查询
需求说明:
查询每个订单的订单号和课程名称以及每个课程的章节的数量.
SELECTc.corder_no,c.cname,COUNT( cs.id ) num
FROMt_course cINNER JOIN t_course_section cs ON c.corder_no = cs.corder_no
GROUP BYc.corder_no,c.cname;
创建VO类
@Data
public class CourseVo {private long corderNo;private String cname;private int num;
}
查询mapper
@Mapper
public interface CourseMapper extends BaseMapper<Course> {@Select({"SELECT \n" +" c.corder_no,\n" +" c.cname,\n" +" COUNT(cs.id) num\n" +"FROM t_course c INNER JOIN t_course_section cs ON c.corder_no = cs.corder_no\n" +"GROUP BY c.corder_no,c.cname"})List<CourseVo> getCourseNameAndSectionNum();}
测试结果
//关联查询@Testpublic void testSelectCourseNameAndSectionNum(){List<CourseVo> list = courseMapper.getCourseNameAndSectionNum();list.forEach(System.out::println);}
2025-09-12 16:48:01.962 INFO 17340 --- [ main] ShardingSphere-SQL : Actual SQL: db0 ::: SELECT c.corder_no,c.cname,COUNT(cs.id) num
FROM t_course_1 c INNER JOIN t_course_section_1 cs ON c.corder_no = cs.corder_no
GROUP BY c.corder_no,c.cname ORDER BY c.corder_no ASC,c.cname ASC
2025-09-12 16:48:01.962 INFO 17340 --- [ main] ShardingSphere-SQL : Actual SQL: db1 ::: SELECT c.corder_no,c.cname,COUNT(cs.id) num
FROM t_course_0 c INNER JOIN t_course_section_0 cs ON c.corder_no = cs.corder_no
GROUP BY c.corder_no,c.cname ORDER BY c.corder_no ASC,c.cname ASC
2025-09-12 16:48:01.962 INFO 17340 --- [ main] ShardingSphere-SQL : Actual SQL: db1 ::: SELECT c.corder_no,c.cname,COUNT(cs.id) num
FROM t_course_1 c INNER JOIN t_course_section_1 cs ON c.corder_no = cs.corder_no
GROUP BY c.corder_no,c.cname ORDER BY c.corder_no ASC,c.cname ASC
CourseVo(corderNo=1000, cname=绑定表0, num=30)
CourseVo(corderNo=1001, cname=绑定表1, num=30)
CourseVo(corderNo=1002, cname=绑定表2, num=30)