使用spring boot集成shardingsphere分库分表简易测试

根据如下pom整上一个spring-boot项目,spring-boot版本用2.3.5,shardingsphere用5.1.1。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.shardingsphere</groupId><artifactId>shardingsphere-test</artifactId><version>1.0-SNAPSHOT</version><!--引入spring boot 2.3.5 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.5.RELEASE</version><relativePath/></parent><dependencies><!--spring boot的web模块--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--引入shardingsphere--><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId><version>5.1.1</version></dependency><!--引入mybatis plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.1</version></dependency><!--引入mysal connector--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!--引入Lombok--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!--引入spring 测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency><!--spring 测试类--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><scope>compile</scope></dependency></dependencies></project>

再用mysql整一个名为shardingsphere-test的库(编码集utf8mb4,也可以选自己喜欢的编码集),再往里弄上两个测试表。

CREATE TABLE t_course_1 (`cid` BIGINT(20) NOT NULL,`user_id` BIGINT(20) DEFAULT NULL,`cname` VARCHAR(50) DEFAULT NULL,`brief` VARCHAR(50) DEFAULT NULL,`price` DOUBLE DEFAULT NULL,`status` INT(11) DEFAULT NULL,PRIMARY KEY (`cid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;CREATE TABLE t_course_2 (`cid` BIGINT(20) NOT NULL,`user_id` BIGINT(20) DEFAULT NULL,`cname` VARCHAR(50) DEFAULT NULL,`brief` VARCHAR(50) DEFAULT NULL,`price` DOUBLE DEFAULT NULL,`status` INT(11) DEFAULT NULL,PRIMARY KEY (`cid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;

项目结构如下。

application.yml的配置及解释如下:

spring:application:name: sharding-jdbc-demo # 应用名称shardingsphere:# 设置全局属性props:# 打开SQL显示功能,将会打印出执行的原始SQL和实际路由后的SQLsql-show: true# 数据源配置datasource:# 定义数据源名称列表,这里只有一个名为db1的数据源names: db1# 数据源db1的具体配置db1:# 数据源实现类,此处使用HikariCP连接池type: com.zaxxer.hikari.HikariDataSource# JDBC驱动类名,对应MySQL数据库驱动driver-class-name: com.mysql.jdbc.Driver# 数据库连接URL,连接本地MySQL服务器上的shardingsphere-test数据库,并设置字符编码和禁用SSLurl: jdbc:mysql://127.0.0.1:3306/shardingsphere-test?characterEncoding=UTF-8&useSSL=false# 数据库用户名username: root# 数据库密码password: root# 规则配置部分rules:# 分片规则相关配置sharding:# 1.定义分片表的实际分布情况tables:# 针对表t_course的分片配置t_course:# 实际数据节点分布,表明t_course表被分成两张表,分别命名为t_course_0和t_course_1,并存储在db1数据库中actual-data-nodes: "db1.t_course_$->{1..2}"# 配置策略table-strategy:# 用于单分片键的标准分片场景standard:sharding-column: cid# 分片算法名字sharding-algorithm-name: course_inline# 分布式主键生成策略配置key-generate-strategy:# 主键列名为cidcolumn: cid# 引用已定义的分布式序列生成器  alg-snowflakekey-generator-name: snowflake# 2.定义分布式序列生成器key-generators:# 定义名为alg-snowflake的分布式序列生成器  alg-snowflakesnowflake:# 类型为SNOWFLAKE算法,用于生成全局唯一IDtype: SNOWFLAKE# 3.定义分片算法sharding-algorithms:# 定义名为table-inline的分片算法course_inline:# 使用INLINE类型的行表达式分片算法type: INLINE# 算法属性配置props:# 行表达式算法具体内容,按照cid模2加1的值来确定数据落入哪张表,例如:cid%2+1=0,则落入t_course_1,等于1则落入t_course_2algorithm-expression: t_course_$->{cid % 2 + 1}# 4.定义分片策略#sharding-strategies:# 对于表t_course的分片策略定义#t_course_strategy:# 使用标准分片策略#type: STANDARD# 指定分片键为cid列#sharding-column: cid# 引用已定义的分片算法#sharding-algorithm-name: course_inline# SQL输出日志
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

再弄一个对应数据库的实体类。

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;@TableName("t_course")
@Data
@ToString
public class Course {//@TableId(type = IdType.AUTO)@TableIdprivate Long cid;private Long userId;private Long corderNo;private String cname;private String brief;private Double price;private Integer status;}

再搞一个mapper。

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shardingsphere.demo.entity.Course;
import org.apache.ibatis.annotations.Mapper;@Mapper
public interface CourseMapper extends BaseMapper<Course> {}

再搞一个service接口。

public interface CoureInterface {public void addCoure();
}

按道上的规矩再搞一个service接口的实现类。

import com.shardingsphere.demo.coure.CoureInterface;
import com.shardingsphere.demo.entity.Course;
import com.shardingsphere.demo.mapper.CourseMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class CoureInterfaceImpl implements CoureInterface {@Autowiredprivate CourseMapper courseMapper;@Overridepublic void addCoure() {for (int i = 0; i < 30; i++) {Course course = new Course();// 注意: cid使用雪花算法配置了(还可以使用MybatisPlus UUID),此处不用配置course.setUserId(1000L + i);course.setCname("ShardingSphere");course.setBrief("ShardingSphere测试");course.setPrice(66.6);course.setStatus(1);courseMapper.insert(course);}}
}

再弄上一个controller,来接收远方的呼唤。

import com.shardingsphere.demo.coure.CoureInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class CourseController {@Autowiredprivate CoureInterface coureInterface;@RequestMapping(path = "/demo/addCourse")public void addCourse(){coureInterface.addCoure();}
}

最后再弄上一个spring boot的启动类,用来启动这个sping boot项目。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ShardingSphereTest {public static void main(String[] args) {SpringApplication.run(ShardingSphereTest.class, args);}
}

我们启动服务后,直接浏览器访问这个接口简单测试一下。

localhost:8080/demo/addCourse

再去数据库看一眼,发现如我们所想,数据已经被拆分到两个表中了。

趁热打铁,我们再进阶一小点,把库也给分了算了。

再找一台机器创建一个跟上面一模一样的数据库(shardingsphere-test),库里的表也跟上面建的一模一样两张表(t_course_1,t_course_2),这样我们就富裕了,有了俩数据库。

需要改造的地方就是我们的application.yml配置文件,加上分库操作。

spring:application:name: sharding-jdbc-demo-database # 应用名称shardingsphere:# 设置全局属性props:# 打开SQL显示功能,将会打印出执行的原始SQL和实际路由后的SQLsql-show: true# 数据源配置datasource:# 定义数据源名称列表,这里有两个数据源(数据的名字可以一样,也可以不一样)names: db1, db2# 数据源db1的具体配置db1:# 数据源实现类,此处使用HikariCP连接池type: com.zaxxer.hikari.HikariDataSource# JDBC驱动类名,对应MySQL数据库驱动driver-class-name: com.mysql.jdbc.Driver# 数据库连接URL,连接本地MySQL服务器上的shardingsphere-test数据库,并设置字符编码和禁用SSLurl: jdbc:mysql://127.0.0.1:3306/shardingsphere-test?characterEncoding=UTF-8&useSSL=false# 数据库用户名username: root# 数据库密码password: root# 数据源db1的具体配置db2:# 数据源实现类,此处使用HikariCP连接池type: com.zaxxer.hikari.HikariDataSource# JDBC驱动类名,对应MySQL数据库驱动driver-class-name: com.mysql.jdbc.Driver# 数据库连接URL,连接本地MySQL服务器上的shardingsphere-test数据库,并设置字符编码和禁用SSLurl: jdbc:mysql://124.223.XXX.XXX:3306/shardingsphere-test?characterEncoding=UTF-8&useSSL=false# 数据库用户名username: root# 数据库密码password: root# 规则配置部分rules:# 分片规则相关配置sharding:# 1.定义分片表的实际分布情况tables:# 针对表t_course的分片配置t_course:# 实际数据节点分布,表明t_course表被分成两张表,分别命名为t_course_0和t_course_1,并存储在db1数据库中actual-data-nodes: "db$->{1..2}.t_course_$->{1..2}"# 配置库策略database-strategy:standard:sharding-column: user_idsharding-algorithm-name: table_inline# 配置表策略table-strategy:# 用于单分片键的标准分片场景standard:sharding-column: cid# 分片算法名字sharding-algorithm-name: course_inline# 分布式主键生成策略配置key-generate-strategy:# 主键列名为cidcolumn: cid# 引用已定义的分布式序列生成器  alg-snowflakekey-generator-name: snowflake# 2.定义分布式序列生成器key-generators:# 定义名为alg-snowflake的分布式序列生成器  alg-snowflakesnowflake:# 类型为SNOWFLAKE算法,用于生成全局唯一IDtype: SNOWFLAKE# 3.定义分片算法sharding-algorithms:#定义库分片算法table_inline:type: INLINEprops:algorithm-expression: db$->{user_id % 2 + 1}# 定义名为table-inline的分片算法,表分片course_inline:# 使用INLINE类型的行表达式分片算法type: INLINE# 算法属性配置props:# 行表达式算法具体内容,按照cid模2加1的值来确定数据落入哪张表,例如:cid%2+1=0,则落入t_course_1,等于1则落入t_course_2algorithm-expression: t_course_$->{cid % 2 + 1}# 4.定义分片策略#sharding-strategies:# 对于表t_course的分片策略定义#t_course_strategy:# 使用标准分片策略#type: STANDARD# 指定分片键为cid列#sharding-column: cid# 引用已定义的分片算法#sharding-algorithm-name: course_inline# SQL输出日志
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

然后重启服务,重新访问localhost:8080/demo/addCourse 调用添加数据的服务接口,此时再查数据库就会发现数据已经被shardingsphere分到不同库的不同表里了。

分库查询

        入库了以后,我们写个测试类尝试查询一下,看看会是怎么样。

@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class MyTest {@Autowired(required = false)private CourseMapper courseMapper;/*** 水平分片:查询所有记录* 查询了两个数据源,每个数据源中使用UNION ALL连接两个表*/@Testpublic void testShardingSelectOne(){List<Course> courses = courseMapper.selectList(null);courses.forEach(System.out::println);}}

我们来看一下查询结果。

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30b0d5a7] was not registered for synchronization because synchronization is not active
JDBC Connection [org.apache.shardingsphere.driver.jdbc.core.connection.ShardingSphereConnection@411e567e] will not be managed by Spring
==>  Preparing: SELECT cid,user_id,cname,brief,price,status FROM t_course 
==> Parameters: 
2024-04-19 21:17:29.909  INFO 25740 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT  cid,user_id,cname,brief,price,status  FROM t_course
2024-04-19 21:17:29.909  INFO 25740 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2024-04-19 21:17:29.910  INFO 25740 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: SELECT  cid,user_id,cname,brief,price,status  FROM t_course_1 UNION ALL SELECT  cid,user_id,cname,brief,price,status  FROM t_course_2
2024-04-19 21:17:29.910  INFO 25740 --- [           main] ShardingSphere-SQL                       : Actual SQL: db2 ::: SELECT  cid,user_id,cname,brief,price,status  FROM t_course_1 UNION ALL SELECT  cid,user_id,cname,brief,price,status  FROM t_course_2
<==    Columns: cid, user_id, cname, brief, price, status
<==        Row: 1781311094111928321, 1000, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==        Row: 1781311097660309505, 1002, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==        Row: 1781311098117488641, 1004, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==        Row: 1781311098650165249, 1006, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==        Row: 1781311097660309506, 1003, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==        Row: 1781311098184597506, 1005, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==        Row: 1781311098650165250, 1007, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==        Row: 1781311096750145537, 1001, ShardingSphere, ShardingSphere尝试查询, 99.0, 1
<==      Total: 8

可以看到,它是把每个库的每张表进行union操作,返回返回总结果。

多表关联查询

        如果我们要是多表查询呢?先建上两张有关联的表来试一下。如下两个数据库分别创建t_order0,t_order1,t_order_item0,t_order_item1,仍然分库分表创建,只不过让t_order和t_order_item有联系,即有如此关联:SELECT o.*,i.* FROM t_order o JOIN t_order_item i ON o.order_no = i.order_no;

CREATE TABLE t_order0 (id BIGINT,order_no VARCHAR(30),user_id BIGINT,amount DECIMAL(10,2),PRIMARY KEY(id) 
);
CREATE TABLE t_order1 (id BIGINT,order_no VARCHAR(30),user_id BIGINT,amount DECIMAL(10,2),PRIMARY KEY(id) 
);CREATE TABLE t_order_item0(id BIGINT,order_no VARCHAR(30),user_id BIGINT,price DECIMAL(10,2),`count` INT,PRIMARY KEY(id)
);CREATE TABLE t_order_item1(id BIGINT,order_no VARCHAR(30),user_id BIGINT,price DECIMAL(10,2),`count` INT,PRIMARY KEY(id)
);

再在配置文件中将这俩表的配置搞好。

spring:application:name: sharding-jdbc-demo-database # 应用名称shardingsphere:# 设置全局属性props:# 打开SQL显示功能,将会打印出执行的原始SQL和实际路由后的SQLsql-show: true# 数据源配置datasource:# 定义数据源名称列表,这里有两个数据源(数据的名字可以一样,也可以不一样)names: db1, db2# 数据源db1的具体配置db1:# 数据源实现类,此处使用HikariCP连接池type: com.zaxxer.hikari.HikariDataSource# JDBC驱动类名,对应MySQL数据库驱动driver-class-name: com.mysql.jdbc.Driver# 数据库连接URL,连接本地MySQL服务器上的shardingsphere-test数据库,并设置字符编码和禁用SSLurl: jdbc:mysql://127.0.0.1:3306/shardingsphere-test?characterEncoding=UTF-8&useSSL=false# 数据库用户名username: root# 数据库密码password: root# 数据源db1的具体配置db2:# 数据源实现类,此处使用HikariCP连接池type: com.zaxxer.hikari.HikariDataSource# JDBC驱动类名,对应MySQL数据库驱动driver-class-name: com.mysql.jdbc.Driver# 数据库连接URL,连接本地MySQL服务器上的shardingsphere-test数据库,并设置字符编码和禁用SSLurl: jdbc:mysql://124.223.XXX.XXX:3306/shardingsphere-test?characterEncoding=UTF-8&useSSL=false# 数据库用户名username: root# 数据库密码password: 123456# 规则配置部分rules:# 分片规则相关配置sharding:# 1.定义分片表的实际分布情况tables:# 针对表t_course的分片配置t_course:# 实际数据节点分布,表明t_course表被分成两张表,分别命名为t_course_0和t_course_1,并存储在db1数据库中actual-data-nodes: "db$->{1..2}.t_course_$->{1..2}"# 配置库策略database-strategy:standard:sharding-column: user_idsharding-algorithm-name: table_inline# 配置表策略table-strategy:# 用于单分片键的标准分片场景standard:sharding-column: cid# 分片算法名字sharding-algorithm-name: course_inline# 分布式主键生成策略配置key-generate-strategy:# 主键列名为cidcolumn: cid# 引用已定义的分布式序列生成器  alg-snowflakekey-generator-name: snowflake#order表的分片分库策略t_order:# 实际数据节点分布,表明t_course表被分成两张表,分别命名为t_course_0和t_course_1,并存储在db1数据库中actual-data-nodes: "db$->{1..2}.t_order$->{0..1}"# 配置分库策略database-strategy:standard:sharding-column: user_idsharding-algorithm-name: order_inline# 配置分表策略table-strategy:# 用于单分片键的标准分片场景,根据order_no的hash值进行分片standard:sharding-column: order_no# 分片算法名字sharding-algorithm-name: order_no_mod# 分布式主键生成策略配置key-generate-strategy:# 主键列名为cidcolumn: id# 引用已定义的分布式序列生成器  alg-snowflakekey-generator-name: snowflake#order表的分片分库策略t_order_item:# 实际数据节点分布,表明t_course表被分成两张表,分别命名为t_course_0和t_course_1,并存储在db1数据库中actual-data-nodes: "db$->{1..2}.t_order_item$->{0..1}"# 配置分库策略database-strategy:standard:sharding-column: user_idsharding-algorithm-name: order_inline# 配置分表策略table-strategy:# 用于单分片键的标准分片场景,根据order_no的hash值进行分片standard:sharding-column: order_no# 分片算法名字sharding-algorithm-name: order_no_mod# 分布式主键生成策略配置key-generate-strategy:# 主键列名为cidcolumn: id# 引用已定义的分布式序列生成器  alg-snowflakekey-generator-name: snowflake# 2.定义分布式序列生成器key-generators:# 定义名为alg-snowflake的分布式序列生成器  alg-snowflakesnowflake:# 类型为SNOWFLAKE算法,用于生成全局唯一IDtype: SNOWFLAKE# 3.定义你想配置表的分片算法sharding-algorithms:#定义库分片算法table_inline:type: INLINEprops:algorithm-expression: db$->{user_id % 2 + 1}# 定义名为table-inline的分片算法,表分片course_inline:# 使用INLINE类型的行表达式分片算法type: INLINE# 算法属性配置props:# 行表达式算法具体内容,按照cid模2加1的值来确定数据落入哪张表,例如:cid%2+1=0,则落入t_course_1,等于1则落入t_course_2algorithm-expression: t_course_$->{cid % 2 + 1}order_inline:type: INLINEprops:algorithm-expression: db$->{user_id % 2 + 1}order_no_mod:# 使用HASH_MOD类型的行表达式分片算法type: HASH_MOD# 算法属性配置props:# 行表达式算法具体内容,sharding-count: 2# 4.定义分片策略#sharding-strategies:# 对于表t_course的分片策略定义#t_course_strategy:# 使用标准分片策略#type: STANDARD# 指定分片键为cid列#sharding-column: cid# 引用已定义的分片算法#sharding-algorithm-name: course_inline# SQL输出日志
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

OrderMapper改造一下,进行表关联。 

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shardingsphere.demo.entity.Order;
import com.shardingsphere.demo.vo.OrderVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface OrderMapper extends BaseMapper<Order> {@Select({"SELECT o.order_no, SUM(i.price * i.count) AS amount","FROM t_order o JOIN t_order_item i ON o.order_no = i.order_no","GROUP BY o.order_no"})List<OrderVo> getOrderAmount();
}

再写个测试方法。

    /*** 测试关联表查询*/@Testpublic void testGetOrderAmount(){List<OrderVo> orderAmountList = orderMapper.getOrderAmount();orderAmountList.forEach(System.out::println);}

看看执行结果:

==>  Preparing: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order o JOIN t_order_item i ON o.order_no = i.order_no GROUP BY o.order_no 
==> Parameters: 
2024-04-19 21:27:52.938  INFO 21784 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order o JOIN t_order_item i ON o.order_no = i.order_no GROUP BY o.order_no
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db2 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order0 o JOIN t_order_item0 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db2 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order1 o JOIN t_order_item0 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db2 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order0 o JOIN t_order_item1 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db2 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order1 o JOIN t_order_item1 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order0 o JOIN t_order_item0 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order1 o JOIN t_order_item0 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order0 o JOIN t_order_item1 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:27:52.939  INFO 21784 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order1 o JOIN t_order_item1 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
<==    Columns: order_no, amount
<==        Row: ShardingSphere1, 40.00
<==        Row: ShardingSphere2, 40.00
<==        Row: ShardingSphere5, 6.00
<==        Row: ShardingSphere6, 6.00
<==      Total: 4

        发现了一个问题:可以看到同一个数据源中,查询的次数是t_ordert_order_item的笛卡尔积数量,但是t_order0中的订单数据只会在对应数据源中t_order_item0,不会在t_order_item1中,所以有些关联查询是没有意义的,那么接下来就引入了绑定表的概念。

绑定表

        指分片规则一致的一组分片表。 使用绑定表进行多表关联查询时,必须使用分片键进行关联,否则会出现笛卡尔积关联或跨库关联,从而影响查询效率。所以我们来配置一下,将t_ordert_order_item绑定一下,只需要在rules这里增加如下配置,如果你的配置文件是.properties类型的,需要这样配:spring.shardingsphere.rules.sharding.binding-tables[0]=t_order,t_order_item

# 规则配置部分rules:# 分片规则相关配置sharding:#绑定表binding-tables:- t_order,t_order_item

再次查询:

==>  Preparing: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order o JOIN t_order_item i ON o.order_no = i.order_no GROUP BY o.order_no 
==> Parameters: 
2024-04-19 21:43:08.069  INFO 24608 --- [           main] ShardingSphere-SQL                       : Logic SQL: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order o JOIN t_order_item i ON o.order_no = i.order_no GROUP BY o.order_no
2024-04-19 21:43:08.069  INFO 24608 --- [           main] ShardingSphere-SQL                       : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2024-04-19 21:43:08.070  INFO 24608 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order0 o JOIN t_order_item0 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:43:08.070  INFO 24608 --- [           main] ShardingSphere-SQL                       : Actual SQL: db1 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order1 o JOIN t_order_item1 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:43:08.070  INFO 24608 --- [           main] ShardingSphere-SQL                       : Actual SQL: db2 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order0 o JOIN t_order_item0 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
2024-04-19 21:43:08.070  INFO 24608 --- [           main] ShardingSphere-SQL                       : Actual SQL: db2 ::: SELECT o.order_no, SUM(i.price * i.count) AS amount FROM t_order1 o JOIN t_order_item1 i ON o.order_no = i.order_no GROUP BY o.order_no ORDER BY o.order_no ASC 
<==    Columns: order_no, amount
<==        Row: ShardingSphere1, 40.00
<==        Row: ShardingSphere2, 40.00
<==        Row: ShardingSphere5, 6.00
<==        Row: ShardingSphere6, 6.00
<==      Total: 4

突然一家伙少了四条查询。

  • 如果不配置绑定表:测试的结果为8个SQL。 多表关联查询会出现笛卡尔积关联。
  • 如果配置绑定表:测试的结果为4个SQL。 多表关联查询不会出现笛卡尔积关联,关联查询效率将大大提升。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/826839.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7-25 念数字

题目链接&#xff1a;7-25 念数字 一. 题目 1. 题目 2. 输入输出格式 3. 输入输出样例 4. 限制 二、代码 1. 代码实现 #include <iostream> #include <string> using namespace std;const string pinyin[] { // 每个数字对应的拼音"ling","yi&…

【Hadoop】- YARN架构[7]

前言 Yarn架构是一个用于管理和调度Hadoop集群资源的系统。它是Hadoop生态系统的一部分&#xff0c;主要用于解决Hadoop中的资源管理问题。 通过使用Yarn架构&#xff0c;Hadoop集群中的不同应用程序可以共享集群资源&#xff0c;并根据需要动态分配和回收资源。这种灵活的资…

验证线缆(汽车线束、网线、多芯线)破损或断开与正常线缆的区别在哪里?依AEM CV-100 k50测试仪

工厂产线生产的线缆&#xff08;汽车线束、网线、多芯线&#xff09;做成成品&#xff0c;即2端都安装好了模块。在这种情况下如何快速的判定此条线缆是合格的呢&#xff0c;此处的合格为物理层面上的合格&#xff08;不会出现开路、短路&#xff09;&#xff0c;也就是最基本保…

client-go源码结构及客户端对象

一、基础知识介绍 1、GVR 和 GVK G Goup资源组&#xff0c;包含一组资源操作的集合VVersion资源版本&#xff0c;用于区分不同API的稳定程度及兼容性RResource资源信息&#xff0c;用于区分不同的资源APIKKind资源对象类型&#xff0c;每个资源对象都需要Kind来区分它自身代表…

冒泡排序c++

题目描述 编程输入n(1≤n≤20)个小于1000非负整数&#xff0c;然后自动按从大到小的顺序输出。&#xff08;冒泡排序&#xff09; 输入 第一行&#xff0c;数的个数n; 第二行&#xff0c;n个非负整数。 输出 由大到小的n个非负整数&#xff0c;每个数占一行。 样例输入 …

restful请求风格的增删改查-----修改and删除

一、修改&#xff08;和添加类似&#xff09; 前端&#xff1a; <script type"text/javascript">function update(){//创建user对象var user {id:$("#id").val(),username:$("#username").val(),password:$("#password").val…

探索VR数字展厅,对企业未来展示新模式

在数字化浪潮的推动下&#xff0c;企业展示也在经历着一场革命&#xff0c;VR数字展厅正在以一种全新的方式重塑我们的生活和工作空间&#xff0c;不仅重塑了客户的观展体验&#xff0c;也为企业营销打开了新的渠道。 VR数字展厅作为实体展厅的数字化延伸&#xff0c;正以其沉浸…

【论文笔记】基于预训练模型的持续学习(Continual Learning)(增量学习,Incremental Learning)

论文链接&#xff1a;Continual Learning with Pre-Trained Models: A Survey 代码链接&#xff1a;Github: LAMDA-PILOT 持续学习&#xff08;Continual Learning, CL&#xff09;旨在使模型在学习新知识的同时能够保留原来的知识信息了&#xff0c;然而现实任务中&#xff…

数据结构––kmp算法(串)

kmp算法作为串的一个重要内容&#xff0c;必然有一定的难度&#xff0c;而在看到各类教辅书里的概念与解释后&#xff0c;其晦涩难懂的内容直接劝退一部分人&#xff0c;现在&#xff0c;让我们来看看吧 KMP解决的问题类型 KMP算法的作用就是在一个已知的字符串中查找子串的位…

hive中建立MySQL表格时有乱码

我们启动hive 建立一个学生students表格 使用desc students查看表格结构时 发现有出现乱码的情况 遇到这种问题 我们可以修改一下 打开MySQL mysql -u root -p123456; 切换数据库 use hive; 执行 修改字段注释字符集 alter table COLUMNS_V2 modify column COMMENT varchar…

【算法一则】反转链表

目录 题目题解进阶 题目 给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], left 2, right 4…

天梯赛 L2-052 吉利矩阵

//r[n]:当前第几列的值。 //l[n]:当前第几行的值。 暴力减止 #include<bits/stdc.h> using namespace std; #define int long long const int n1e3; int a,b,c,l[n],r[n],an; void dfs(int x,int y) {if(xb1){an;return ;}for(int i0;i<a;i){l[x]i;r[y]i;if(l[x]&l…

JavaScript之模块化规范详解

文章的更新路线&#xff1a;JavaScript基础知识-Vue2基础知识-Vue3基础知识-TypeScript基础知识-网络基础知识-浏览器基础知识-项目优化知识-项目实战经验-前端温习题&#xff08;HTML基础知识和CSS基础知识已经更新完毕&#xff09; 正文 CommonJS、UMD、CMD和ES6是不同的模块…

详解Java中的五种IO模型

文章目录 前言1、内核空间和用户空间2、用户态和内核态3、上下文切换4、虚拟内存5、DMA技术6、传统 IO 的执行流程 一、阻塞IO模型二、非阻塞IO模型三、IO多路复用模型1、IO多路复用之select2、IO多路复用之epoll3、总结select、poll、epoll的区别 四、IO模型之信号驱动模型五、…

网络安全产品---态势感知EDR

态势感知 what SA&#xff0c;Situational Awareness 是对一定时间和空间内的环境元素进行感知&#xff0c;并对这些元素的含义进行理解&#xff0c;最终预测这些元素在未来的发展状态。 why 安全防护思想已经从过去的被动防御向主动防护和智能防护转变。如果不做到主动防御…

Hadoop1X,Hadoop2X和hadoop3X有很大的区别么?

Hadoop的演进从Hadoop 1到Hadoop 3主要是为了提供更高的效率、更好的资源管理、更高的可靠性以及对更多数据处理方式的支持。下面是Hadoop 1, Hadoop 2, 和 Hadoop 3之间的主要区别和演进的原因&#xff1a; Hadoop 1 特点&#xff1a; 主要包括两大核心组件&#xff1a;HDFS&a…

跨平台SIP 客户端-linphone下载、使用、开启视频H264

linphone 介绍 Linphone 是一种开源的语音和视频通信应用程序&#xff0c;它提供了基于互联网协议&#xff08;IP&#xff09;的实时通信功能。用于语音/视频通话、即时消息和电话会议的开源 SIP 电话。它适用于移动和桌面环境&#xff08;iOS、Android、GNU/Linux、macOS、Win…

【Linux】在centos快速搭建K8S1.18集群

使用 kubeadm 创建集群帮助文档 如果您需要以下几点&#xff0c;该工具是很好的选择&#xff1a;kubeadm 一种简单的方法&#xff0c;让你尝试 Kubernetes&#xff0c;可能是第一次。现有用户自动设置群集并测试其应用程序的一种方式。其他生态系统和/或安装程序工具中的构建…

SpringBoot集成Sleuth

引入Maven依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId></dependency> 配置yml文件 bootstrap.yml文件增加如下配置 注&#xff1a;这个配置不是必须要&#…

经典机器学习算法——决策树

优质博文&#xff1a;IT-BLOG-CN 树模型是机器学习中最常用的一类模型&#xff0c;包括随机森林、AdaBoost、GBDT&#xff08;XGBoost和Lightgbm&#xff09;等&#xff0c;基本原理都是通过集成弱学习器的即式来进一步提升准确度。这里的弱学习器包括线性模型和决策树模型&…