分库分表之实战-sharding-JDBC绑定表配置实战

大家好,我是工藤学编程 🦉 一个正在努力学习的小博主,期待你的关注
实战代码系列最新文章😉 C++实现图书管理系统(Qt C++ GUI界面版)
SpringBoot实战系列🐷 【SpringBoot实战系列】Sharding-Jdbc实现分库分表到分布式ID生成器Snowflake自定义wrokId实战
环境搭建大集合 环境搭建大集合(持续更新)
分库分表 分库分表之实战-sharding-JDBC水平分库+水平分表配置实战

前情摘要:

1、数据库性能优化
2、分库分表之优缺点分析
3、分库分表之数据库分片分类
4、分库分表之策略
5、分库分表技术栈讲解-Sharding-JDBC
6、分库分表下的 ID 冲突问题与雪花算法讲解
7、分库分表之实战-sharding-JDBC
8、分库分表之实战-sharding-JDBC广播表
9、分库分表之实战-sharding-JDBC水平分库+水平分表配置实战


【亲测宝藏】发现一个让 AI 学习秒变轻松的神站!不用啃高数、不用怕编程,高中生都能看懂的人工智能教程来啦!

👉点击跳转,和 thousands of 小伙伴一起用快乐学习法征服 AI,说不定下一个开发出爆款 AI 程序的就是你!


本文章目录

Sharding-Jdbc绑定表

在分布式数据库分片中,多表关联查询一直是性能优化的难点。Sharding-Jdbc提供的绑定表机制,正是为解决同规则分片子表关联问题而生。本文将从核心概念出发,详解绑定表的作用原理,并通过实战案例演示配置过程,帮助你在分布式场景下提升关联查询效率。

一、什么是绑定表?

绑定表指分片规则完全一致的主表与子表。当两张表的分片策略(包括分片键、分片算法)完全相同时,它们就可以建立绑定关系。

举个典型例子:

  • 主表product_order(订单表)按order_id分片
  • 子表product_order_item(订单项表)也按order_id分片

这两张表就互为绑定表。因为它们的分片规则一致,所有order_id=100的记录,都会落入同一个分片(比如分片1),不会出现主表在分片1而子表在分片2的情况。

二、为什么需要绑定表?

没有绑定表时,多表关联会面临两个严重问题:

  1. 笛卡尔积查询灾难

    假设订单表和订单项表各分为3个分片,未配置绑定表时,Sharding-Jdbc会执行3×3=9次跨分片关联(每个分片的主表关联所有分片的子表),产生大量无效计算。

  2. 数据关联错误

    跨分片关联可能导致本应匹配的记录被分散在不同分片,出现查询结果缺失或冗余。

而绑定表通过强制同分片关联,让关联查询仅在相同分片内执行(如分片1的主表只关联分片1的子表),从根本上避免了笛卡尔积,同时保证数据关联的准确性。

三、绑定表配置实战

product_orderproduct_order_item为例,演示如何在Sharding-Jdbc中配置绑定表。

1. sql执行与实体编写

product_order我们已经在之前的项目分库分表之实战-sharding-JDBC水平分库+水平分表配置实战中完成并创建了,接下了我们只需新增product_order_item,我们需要分别执行sql如下:

  • 在ccc_shop_order_0中执行如下sql
sql 复制代码
CREATE TABLE `product_order_item_0` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `product_order_id` bigint DEFAULT NULL COMMENT '订
单号',
  `product_id` bigint DEFAULT NULL COMMENT '产品id',
  `product_name` varchar(128) DEFAULT NULL COMMENT 
'商品名称',
  `buy_num` int DEFAULT NULL COMMENT '购买数量',
  `user_id` bigint DEFAULT NULL,
  PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT 
CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
sql 复制代码
CREATE TABLE `product_order_item_1` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `product_order_id` bigint DEFAULT NULL COMMENT '订
单号',
  `product_id` bigint DEFAULT NULL COMMENT '产品id',
  `product_name` varchar(128) DEFAULT NULL COMMENT 
'商品名称',
  `buy_num` int DEFAULT NULL COMMENT '购买数量',
  `user_id` bigint DEFAULT NULL,
  PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT 
CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
  • 在ccc_shop_order_1中执行如下sql
sql 复制代码
CREATE TABLE `product_order_item_0` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `product_order_id` bigint DEFAULT NULL COMMENT '订
单号',
  `product_id` bigint DEFAULT NULL COMMENT '产品id',
  `product_name` varchar(128) DEFAULT NULL COMMENT 
'商品名称',
  `buy_num` int DEFAULT NULL COMMENT '购买数量',
  `user_id` bigint DEFAULT NULL,
  PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT 
CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
sql 复制代码
CREATE TABLE `product_order_item_1` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `product_order_id` bigint DEFAULT NULL COMMENT '订
单号',
  `product_id` bigint DEFAULT NULL COMMENT '产品id',
  `product_name` varchar(128) DEFAULT NULL COMMENT 
'商品名称',
  `buy_num` int DEFAULT NULL COMMENT '购买数量',
  `user_id` bigint DEFAULT NULL,
  PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT 
CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

创建完成之后,我们创建对应实体类ProductOrderItemDO

java 复制代码
@Data
@TableName("product_order_item")
@EqualsAndHashCode(callSuper = false)
public class ProductOrderItemDO {
    private Long id;
    
    private Long productOrderId;
    
    private Long productId;
    
    private String productName;
    
    private Integer buyNum;
    
    private Long userId;
}

同时新建对应的mapper ProductOrderItemMapper,同时在ProductOrderMapper中编写关联查询语句

java 复制代码
public interface ProductOrderItemMapper extends
        BaseMapper<ProductOrderItemDO> {
}

public interface ProductOrderMapper extends
        BaseMapper<ProductOrderDO> {
    @Select("select * from product_order o left join product_order_item i on o.id = i.product_order_id")
    List<Object>listProductOrderDetail();
}

为了测试绑定表的作用,我们可以先在DbTest编写一个单元测试函数去测试其发出的sql是怎么样的

java 复制代码
@Test
    public void testBingding(){
        List<Object> list = productOrderMapper.listProductOrderDetail();
        System.out.println(list);
    }

测试结果如上,可以看到。由于我们的product_order和product_order_item他们的分库和分表策略完全一致,因此正常来说,我们只需要去关联查询对应的表就好了,但是这里确发出了整整多出一倍的sql,因此配置绑定表是很有必要的

2. 核心配置步骤

(1)配置绑定表关系

在上述配置基础上,通过binding-tables指定绑定表组:

yaml 复制代码
#绑定表
spring.shardingsphere.sharding.binding‐tables[0] =product_order,product_order_item

配置说明

  • 绑定表组以逗号分隔多个表名,组内所有表必须使用相同的分片键和分片算法
  • 一个绑定组可以包含多个表(如"订单表-订单项表-物流表"三表绑定)

此时,我们再次执行我们的测试函数观察发出的sql

可以观察到,现在变成了正常的四条

四、绑定表查询原理

当执行关联查询时,Sharding-Jdbc会:

  1. 识别SQL中的主表(通常是FROM后的第一个表)
  2. 根据主表的分片键值计算目标分片(如order_id=100落在分片1)
  3. 强制子表查询仅在主表所在的分片内执行(避免跨分片扫描)
  • 未配置绑定表:可能扫描所有分片的product_orderproduct_order_item,执行2×2=4次关联
  • 配置绑定表后:仅查询分片1的两张表,1次关联即可完成

五、注意事项

  1. 分片规则必须完全一致

    绑定表的分片键、分片算法、分片数量必须严格相同,否则会导致数据关联异常。

  2. 主表选择影响查询效率

    Sharding-Jdbc以FROM后的第一个表作为主表计算分片,建议将数据量较大的表放在前面。

  3. 与广播表的区别

    广播表是全分片同步的表(如字典表),而绑定表是按相同规则分片的表,二者适用场景不同。

  4. 多表绑定需注意顺序

    超过2张表绑定时,确保所有表的分片逻辑一致,避免部分表出现跨分片关联。

六、总结

绑定表是Sharding-Jdbc优化同规则分片子表关联的核心机制,通过约束分片规则一致性,从根源上解决了多表关联的笛卡尔积问题。在实际项目中,只要涉及分片子表的JOIN查询,就应该优先配置绑定表,这能显著降低跨分片计算开销,提升分布式查询的稳定性。

觉得有用请点赞收藏!

如果有相关问题,欢迎评论区留言讨论~

相关推荐
JOEH6020 分钟前
Java 后端开发中的内存泄漏问题:90% 开发者都会踩的 5 个坑
后端
_野猪佩奇_牛马版20 分钟前
多智能体协作 - 使用 LangGraph 子图实现
后端
JOEH6021 分钟前
为什么你的数据库连接总超时?99% 的 Java 程序员都踩过这 5 个坑
后端
后端不背锅22 分钟前
对外接口设计完全指南:安全、高性能、可演进
后端
爱丽_32 分钟前
Redis 分布式锁:SET NX、过期时间、续租、可重入、Redlock 与坑
数据库·redis·分布式
IT小崔38 分钟前
SqlSugar 使用教程
数据库·后端
Oneslide39 分钟前
Docker Compose 重启 RabbitMQ 数据丢失?
后端
架构师沉默41 分钟前
为什么国外程序员都写独立博客,而国内都在公众号?
java·后端·架构
开心就好20251 小时前
Win11 抓包工具怎么选?网页请求与设备流量抓取
后端·ios
GIS阵地1 小时前
QgsProviderMetadata 详解(基于 QGIS 3.40.13 API)
数据库·qt·arcgis·oracle·gis·开源软件·qgis