9Sharding-JDBC 多租户实战 · SpringCloud微服务实战 · 看云

导航

本节代码地址


本节演示的例子是以实际业务中发生的场景来演示

  • 首先对于已经分过库的租户,在新增租户后不能影响现有的分库
  • 对于公共表,希望存储在固定的位置,不参与分库分表

那么针对以上情况,我们需要分析分库的条件是什么?是否还需要分表?
答:根据标题相信你应该猜到了,我们根据租户去分库,不用取模分库,本节我们演示只分库的场景。

本节代码地址

GitHub:


项目技术栈

技术栈 版本
jdk 1.8.0_161
SpringBoot 2.2.2.RELEASE
Shardingsphere 4.0.1
Mybatis-plus 3.3.0
Hutool 5.0.6
HikariCP 2.7.9
  • SpringBoot 基于SpringBoot 2.2.2.RELEASE 构建我们的应用
  • Shardingsphere 使用最新版的4.0.1来支撑读写分离
  • Mybatis-plus来作为我们的持久层框架,介绍代码的开发量
  • Hutool作为java工具包
  • HikariCP 项目中的连接池,性能要比Druid要高,目前SpringBoot 默认支持的数据连接池。
  • lombok 使代码简介,介绍getter\setter\构造器的创建,需要在idea中安装lombok插件

1. 数据库创建

1.1 新建数据库

mysql 数据库的搭建可以参考容器化章节(docker run 一个)

1.2 执行脚本

执行以下脚本将创建数据库tenant_niketenant_conversetenant_adidastenant_common,并在库里面创建sys_usersys_user_commonsys_user_union

CREATE DATABASE tenant_nike;
USE tenant_nike;
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `update_user` varchar(100) NOT NULL COMMENT '修改人编码',
  `delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记(1 删除 0未删除)',
  `pos_code` varchar(50) DEFAULT NULL COMMENT '职位编码',
  `disable_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用标记(1 禁用 0启用)',
  `avatar` varchar(100) DEFAULT NULL COMMENT '头像地址',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `password` varchar(100) DEFAULT NULL COMMENT '密码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `dept_code` varchar(50) DEFAULT NULL COMMENT '部门编码',
  `user_phone` varchar(15) DEFAULT NULL COMMENT '手机号',
  `tenant` varchar(15) DEFAULT NULL COMMENT '租户',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `idx_email` (`email`) USING BTREE COMMENT '邮箱索引',
  UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE COMMENT '用户名索引',
  KEY `idx_dept_code` (`dept_code`) USING BTREE COMMENT '部门编码索引',
  KEY `idx_position_code` (`pos_code`) USING BTREE COMMENT '职位编码索引'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='系统用户表';
DROP TABLE IF EXISTS `sys_user_common`;
CREATE TABLE `sys_user_common` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1248171346601271299 DEFAULT CHARSET=utf8 COMMENT='系统用户表';
DROP TABLE IF EXISTS `sys_user_union`;
CREATE TABLE `sys_user_union` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1248171346601271299 DEFAULT CHARSET=utf8 COMMENT='系统用户表union';

CREATE DATABASE tenant_adidas;
USE tenant_adidas;
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `update_user` varchar(100) NOT NULL COMMENT '修改人编码',
  `delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记(1 删除 0未删除)',
  `pos_code` varchar(50) DEFAULT NULL COMMENT '职位编码',
  `disable_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用标记(1 禁用 0启用)',
  `avatar` varchar(100) DEFAULT NULL COMMENT '头像地址',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `password` varchar(100) DEFAULT NULL COMMENT '密码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `dept_code` varchar(50) DEFAULT NULL COMMENT '部门编码',
  `user_phone` varchar(15) DEFAULT NULL COMMENT '手机号',
  `tenant` varchar(15) DEFAULT NULL COMMENT '租户',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `idx_email` (`email`) USING BTREE COMMENT '邮箱索引',
  UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE COMMENT '用户名索引',
  KEY `idx_dept_code` (`dept_code`) USING BTREE COMMENT '部门编码索引',
  KEY `idx_position_code` (`pos_code`) USING BTREE COMMENT '职位编码索引'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='系统用户表';
DROP TABLE IF EXISTS `sys_user_common`;
CREATE TABLE `sys_user_common` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1248171346601271299 DEFAULT CHARSET=utf8 COMMENT='系统用户表';
DROP TABLE IF EXISTS `sys_user_union`;
CREATE TABLE `sys_user_union` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1248171346601271299 DEFAULT CHARSET=utf8 COMMENT='系统用户表union';

CREATE DATABASE tenant_converse;
USE tenant_converse;
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `update_user` varchar(100) NOT NULL COMMENT '修改人编码',
  `delete_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记(1 删除 0未删除)',
  `pos_code` varchar(50) DEFAULT NULL COMMENT '职位编码',
  `disable_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '启用标记(1 禁用 0启用)',
  `avatar` varchar(100) DEFAULT NULL COMMENT '头像地址',
  `email` varchar(50) DEFAULT NULL COMMENT '邮箱',
  `password` varchar(100) DEFAULT NULL COMMENT '密码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
  `dept_code` varchar(50) DEFAULT NULL COMMENT '部门编码',
  `user_phone` varchar(15) DEFAULT NULL COMMENT '手机号',
  `tenant` varchar(15) DEFAULT NULL COMMENT '租户',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `idx_email` (`email`) USING BTREE COMMENT '邮箱索引',
  UNIQUE KEY `idx_user_name` (`user_name`) USING BTREE COMMENT '用户名索引',
  KEY `idx_dept_code` (`dept_code`) USING BTREE COMMENT '部门编码索引',
  KEY `idx_position_code` (`pos_code`) USING BTREE COMMENT '职位编码索引'
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='系统用户表';

DROP TABLE IF EXISTS `sys_user_common`;
CREATE TABLE `sys_user_common` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1248171346601271299 DEFAULT CHARSET=utf8 COMMENT='系统用户表';
DROP TABLE IF EXISTS `sys_user_union`;
CREATE TABLE `sys_user_union` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1248171346601271299 DEFAULT CHARSET=utf8 COMMENT='系统用户表union';
CREATE DATABASE tenant_common;
USE tenant_common;
DROP TABLE IF EXISTS `sys_user_common`;
CREATE TABLE `sys_user_common` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
  `create_user` varchar(100) NOT NULL COMMENT '创建人编码',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1248171346601271299 DEFAULT CHARSET=utf8 COMMENT='系统用户表';

2. 新建读写分离模块shardingsphere-learning-sub-db

上面我们已经配置了公共的针对用户表的基本操作,这些暂时已经够我们演示用了,如果不够,可以自定义自己的实现

2.1 添加依赖

这里我们将shardingsphere-learning-common的包依赖进来,方便我们操作用户表的增删改查

<dependencies>
    <dependency>
        <groupId>com.yisu.fwcloud</groupId>
        <artifactId>shardingsphere-learning-common</artifactId>
        <version>${version}</version>
    </dependency>
</dependencies>

2.2 新建实体

因为公共的实体只有用户实体,暂时不满足测试要求,因此新建两个实体,一个用于测试公共表,一个用于测试绑定表的查询

@Data
@TableName("sys_user_common")
@EqualsAndHashCode(callSuper=false)
public class SysUserCommon {
    
    @TableId(value = "id", type = IdType.ID_WORKER)
    private Long id;
    
    private Date createTime;
    
    private String createUser;

    
    private String userName;
}
@Data
@TableName("sys_user_union")
@EqualsAndHashCode(callSuper=false)
public class SysUserUnion {
    
    @TableId(value = "id", type = IdType.ID_WORKER)
    private Long id;
    
    private Date createTime;
    
    private String createUser;

    
    private String userName;
}


2.3 新建Mapper


public interface SysUserCommonMapper extends BaseMapper<SysUserCommon> {



}

public interface SysUserUnionMapper extends BaseMapper<SysUserCommon> {



}

这里不直接用公供封装的mapper是因为不想影响公共的mapper,并且我们需要在mapper中自定一些方法,因此单独建了一个mapper,这里我们将测试业务表关联广播表(可以理解为全局表)的测试,以及使用绑定关系测试关联表,具体的Xml实现可以看源码,地址在上面。


public interface SysUserPublicMapper extends BaseMapper<SysUser> {


    
    SysUser getUserUnionCommon(@Param("username") String username,@Param("id") Long id);

    
    SysUser getUserUnionCommonByTenant(@Param("username") String username,@Param("tenant") String tenant);


    
    SysUser getUserUnionByUserName(@Param("username") String username,@Param("tenant") String tenant);

}


2.4 应用配置

这里笔者将默认的端口修改为了8900,然后就是配置Sharding-JDBC的数据源,我们本节演示的Sharding-JDBC读写分离需要两个库(真实项目中需要两个数据库实例)。

  1. 笔者在配置中先设置数据源的名称
  2. 配置数据库连接信息,如spring.shardingsphere.datasource.{数据源名称}.type
  3. 配置分库逻辑
  4. 配置广播表
  5. 配置绑定表
  6. 将sql日志信息打印出来

这里要解释一下,
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=tenant-$->{tenant},实际上可以满足我们的需要,实际上这里的分库指的就是我们配置的数据源ds,tenant-nike,tenant-converse,tenant-adidas,而tenant-后面的就是我们租户具体的值。另一个不在规则内的就是我们需要配置的广播表的固定存储位置

在最后面我们也添加了mybatis-plus xml文件扫描的位置,方便我们自定义sql语句

server.port=8900

#数据源定义
spring.shardingsphere.datasource.names=ds,tenant-nike,tenant-converse,tenant-adidas

# 数据源 nike
spring.shardingsphere.datasource.tenant-nike.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.tenant-nike.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.tenant-nike.jdbc-url=jdbc:mysql://${dbIp}:3306/tenant_nike?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.tenant-nike.username=root
spring.shardingsphere.datasource.tenant-nike.password=123456

# 数据源 converse
spring.shardingsphere.datasource.tenant-converse.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.tenant-converse.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.tenant-converse.jdbc-url=jdbc:mysql://${dbIp}:3306/tenant_converse?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.tenant-converse.username=root
spring.shardingsphere.datasource.tenant-converse.password=123456

# 数据源 adidas
spring.shardingsphere.datasource.tenant-adidas.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.tenant-adidas.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.tenant-adidas.jdbc-url=jdbc:mysql://${dbIp}:3306/tenant_adidas?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.tenant-adidas.username=root
spring.shardingsphere.datasource.tenant-adidas.password=123456

# 数据源 广播库
spring.shardingsphere.datasource.ds.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds.jdbc-url=jdbc:mysql://${dbIp}:3306/tenant_common?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
spring.shardingsphere.datasource.ds.username=root
spring.shardingsphere.datasource.ds.password=123456


spring.shardingsphere.sharding.default-data-source-name=ds

#根据username分库
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=tenant
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=tenant-$->{tenant}
#spring.shardingsphere.sharding.default-database-strategy.standard.precise-algorithm-class-name=com.yisu.shardingsphere.config.MyShardingDatabaseAlgorithm

# 表配置
spring.shardingsphere.sharding.tables.sys_user.actual-data-nodes=tenant-${['adidas','nike','converse']}.sys_user
# 广播表
#spring.shardingsphere.sharding.shardingRule.broadcast-tables=sys_user_common
#spring.shardingsphere.sharding.broadcast-tables=sys_user_common
# 有点坑....
spring.shardingsphere.sharding.tables.sys_user_common.actual-data-nodes=ds.sys_user_common  
#绑定表
spring.shardingsphere.ds.shardingRule.binding-tables[0]=sys_user,sys_user_union
#打印sql
spring.shardingsphere.props.sql.show=true
spring.main.allow-bean-definition-overriding=true

# mybatis plus
mybatis-plus.mapper-locations=classpath:/mapper

2.5 新建启动类


@SpringBootApplication
public class FwShardingsphereSubDb{

    public static void main(String[] args) {
        SpringApplication.run(FwShardingsphereSubDb.class, args);
    }

}

2.6 新建单元测试

2.6.1 批量新增业务数据(sys_user)测试

新建单元测试,测试数据会不会按租户进行分库,可以看到方法中,笔者设置的租户值和库名是对应的。

@Test
public void testBatch(){

    List<String> tenantList = Lists.newArrayList("nike", "adidas", "converse");
    List<SysUser> list=new ArrayList<>();
    for (int i = 0; i <100 ; i++) {


        SysUser sysUser=new SysUser();
        sysUser.setAvatar("/home/avatar");
        sysUser.setCreateTime(DateUtil.date());
        sysUser.setCreateUser("sys"+i);
        sysUser.setDeleteFlag(0);
        sysUser.setDeptCode("depe"+i);
        sysUser.setDisableFlag(0);
        sysUser.setEmail("***@123.com"+i);
        sysUser.setPassword("123456");
        sysUser.setPosCode("pos");
        sysUser.setRealName("realname"+i);
        sysUser.setUpdateTime(DateUtil.date());
        sysUser.setUserName("fwcloud"+i);
        sysUser.setUpdateUser("sys"+i);
        sysUser.setUserPhone("12345678912"+i);
        sysUser.setTenant(tenantList.get(new Random().nextInt(tenantList.size())));
        list.add(sysUser);
    }

    boolean saveBatch = sysUserService.saveBatch(list);
    Assert.assertEquals(true,saveBatch);
}

我们到数据库中验证之后,可以看到数据均落到对应的库中,具体数据如下
tenant_adidas库中的数据
fdb805c19eb5ac237008dab36f0b8ae7_MD5.png

tenant_nike库中的数据
a5e616b0a18b48369ea1123030073a39_MD5.png

tenant_converse库中的数据
aa15f1ae1c165e4f1fa2576f44f5e221_MD5.png

2.6.2 批量新增公共数据(sys_user_common)测试

这里测试就是全局表的功能,我们在配置里面,配置了全局表的库,就是tenant_common库,我们看数据会不会只新增到这里


@Test
public void saveCommonTest(){


    for (int i = 0; i <10 ; i++) {
        sysUserCommonMapper.insert(initSysCommon());
    }
    log.info("save  ok");

}

可以验证的是,数据只新增到了指定的库(tenant_common)
6b36c0caf0c223cf2928bd21482e3c5d_MD5.png

2.6.3 公共数据(sys_user_common)查询测试


@Test
public void testSelect(){
    List<SysUserCommon> sysUserCommons = sysUserCommonMapper.selectList(null);
    log.info(JSONUtil.toJsonStr(sysUserCommons));
}

控制台日志如下,可以看到,走的数据源就是我们配置的全局表所在库

2020-04-11 22:10:33.113 DEBUG 33984 --- [           main] c.y.s.d.m.S.selectList                   : ==>  Preparing: SELECT id,create_time,create_user,user_name FROM sys_user_common 
2020-04-11 22:10:33.138 DEBUG 33984 --- [           main] c.y.s.d.m.S.selectList                   : ==> Parameters: 
2020-04-11 22:10:33.758  INFO 33984 --- [           main] ShardingSphere-SQL                       : Rule Type: sharding
2020-04-11 22:10:33.758  INFO 33984 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT  id,create_time,create_user,user_name  FROM sys_user_common
2020-04-11 22:10:33.758  INFO 33984 --- [           main] ShardingSphere-SQL                       : SQLStatement: SelectSQLStatementContext(super=CommonSQLStatementContext(sqlStatement=org.apache.shardingsphere.sql.parser.sql.statement.dml.SelectStatement@402c9a60, tablesContext=TablesContext(tables=[Table(name=sys_user_common, alias=Optional.absent())], schema=Optional.absent())), projectionsContext=ProjectionsContext(startIndex=8, stopIndex=43, distinctRow=false, projections=[ColumnProjection(owner=null, name=id, alias=Optional.absent()), ColumnProjection(owner=null, name=create_time, alias=Optional.absent()), ColumnProjection(owner=null, name=create_user, alias=Optional.absent()), ColumnProjection(owner=null, name=user_name, alias=Optional.absent())], columnLabels=[id, create_time, create_user, user_name]), groupByContext=org.apache.shardingsphere.sql.parser.relation.segment.select.groupby.GroupByContext@7d43f1c9, orderByContext=org.apache.shardingsphere.sql.parser.relation.segment.select.orderby.OrderByContext@eddc9bb, paginationContext=org.apache.shardingsphere.sql.parser.relation.segment.select.pagination.PaginationContext@11e3d08, containsSubquery=false)
2020-04-11 22:10:33.759  INFO 33984 --- [           main] ShardingSphere-SQL                       : Actual SQL: ds ::: SELECT  id,create_time,create_user,user_name  FROM sys_user_common
2020-04-11 22:10:34.293 DEBUG 33984 --- [           main] c.y.s.d.m.S.selectList                   : <==      Total: 10
2020-04-11 22:10:34.325  INFO 33984 --- [           main] c.y.s.db.mapper.SysUserCommonMapperTest  : [{"createTime":1586614088551,"createUser":"sys","id":1248976130803724289,"userName":"user_name4"},{"createTime":1586614090219,"createUser":"sys","id":1248976135522316290,"userName":"user_name7"},{"createTime":1586614090377,"createUser":"sys","id":1248976136189210626,"userName":"user_name0"},{"createTime":1586614090488,"createUser":"sys","id":1248976136646389761,"userName":"user_name7"},{"createTime":1586614090530,"createUser":"sys","id":1248976136826744833,"userName":"user_name4"},{"createTime":1586614090560,"createUser":"sys","id":1248976136956768258,"userName":"user_name7"},{"createTime":1586614090586,"createUser":"sys","id":1248976137057431554,"userName":"user_name3"},{"createTime":1586614090629,"createUser":"sys","id":1248976137237786625,"userName":"user_name9"},{"createTime":1586614090656,"createUser":"sys","id":1248976137351032833,"userName":"user_name0"},{"createTime":1586614090686,"createUser":"sys","id":1248976137476861954,"userName":"user_name4"}]


2.6.4 验证业务表关联公共表的查询

@Test
public void getUserUnionCommonByTenantTest(){
    SysUser unionCommon = sysUserMapper.getUserUnionCommonByTenant("fwcloud0","adidas");
    log.info(JSONUtil.toJsonStr(unionCommon));
    System.out.println("ok");
}

结果可以看到是不允许这么操作,应为已经跨数据源查询了(我们已经指定了广播表所在的数据源了)
5b8b3893ec5f9b67432dd05b4e1f7a26_MD5.png

2.6.5 验证绑定表关联公共表的查询

@Test
public void getUserUnionByUserNameTest(){
    long start = System.currentTimeMillis();
    SysUser unionCommon = sysUserMapper.getUserUnionByUserName("fwcloud0","adidas");
    log.info(JSONUtil.toJsonStr(unionCommon));
    long end = System.currentTimeMillis();
    System.out.println("time:"+(end-start));
}

数据库里面的数据是36条,数据并不多
在配置了spring.shardingsphere.ds.shardingRule.binding-tables[0]=sys_user,sys_user_union
用时time:1059ms
没有配置
用时time:1594ms

可以看到如果绑定了关联表,交表查询速度变快了,是因为减少了笛卡尔积的操作