使用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.hqwc.cn/news/637930.html

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

相关文章

学习微服务nacos遇到的问题

在学习微服务注册到nacos的时候&#xff0c;所有过程都正确了&#xff0c;注册也成功了&#xff0c;但是访问不了调用的地址报错出现问题。 一、引入依赖 在cloud-demo父工程的pom文件中的<dependencyManagement>中引入SpringCloudAlibaba的依赖 1、springboot <pa…

数据结构 - 顺序表

一. 线性表的概念 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;也就说是连续的…

回归预测 | Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测

回归预测 | Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测 目录 回归预测 | Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现BO-RF贝叶斯优化随机森林多变量回归预测&#xff1b; 2.输入7个特征&#xf…

【Linux】学习记录_14_线程

14 线程 14.1 线程和进程 进程是资源管理的最小单位&#xff0c;每个进程都有数据段、代码段和堆栈段&#xff0c;进程切换时都有复杂的上下文切换等动作。进程切换上下文时&#xff0c; 需要重新映射虚拟地址空间、进出OS内核、寄存器切换&#xff0c;还会干扰处理器的缓存机…

探索NDWI:归一化水体指数的意义与应用

随着遥感技术的不断发展&#xff0c;NDWI&#xff08;Normalized Difference Water Index&#xff0c;归一化水体指数&#xff09;作为一种重要的植被指数&#xff0c;被广泛应用于水资源管理、湿地监测和环境保护等领域。本文将介绍NDWI的意义、计算方法以及在不同领域的应用。…

kettle从入门到精通 第五十三课 ETL之kettle MQTT/RabbitMQ consumer实战

1、上一节课我们学习了MQTT producer 生产者步骤&#xff0c;MQTT consumer消费者步骤。该步骤可以从支持MRQTT协议的中间件获取数据&#xff0c;该步骤和kafka consumer 一样可以处理实时数据交互&#xff0c;如下图所示&#xff1a; 2、双击步骤打开MQTT consumer 配置窗口&a…

golang学习笔记(net/http库基本使用)

关于net/http库 我们先看看标准库net/http如何处理一个请求。 import ("fmt""log""net/http" )var count 0func main() {http.HandleFunc("/", handler)http.HandleFunc("/count", counter)log.Fatal(http.ListenAndServ…

ChatGPT研究论文提示词集合2-【形成假设、设计研究方法】

点击下方▼▼▼▼链接直达AIPaperPass &#xff01; AIPaperPass - AI论文写作指导平台 目录 1.形成假设 2.设计研究方法 3.书籍介绍 AIPaperPass智能论文写作平台 近期小编按照学术论文的流程&#xff0c;精心准备一套学术研究各个流程的提示词集合。总共14个步骤&#…

【设计模式】单例模式|最常用的设计模式

写在前面 单例模式是最常用的设计模式之一&#xff0c;虽然简单&#xff0c;但是还是有一些小坑点需要注意。本文介绍单例模式并使用go语言实现一遍单例模式。 单例模式介绍 简介 单例模式保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 使用场景&#…

Hadoop高可用(High Availability)

Hadoop HA&#xff08;High Availability&#xff09; Hadoop 的高可用性&#xff0c;重点是确保存储&#xff08;HDFS&#xff09;和计算&#xff08;YARN&#xff09;资源在面对节点故障时能够继续正常运行。 1.概述 所谓HA&#xff08;High Availablity&#xff09;&…

Linux动态追踪——eBPF

目录 摘要 1 什么是 eBPF 2 eBPF 支持的功能 3 BCC 4 编写脚本 5 总结 6 附 摘要 ftrace 和 perf 与 ebpf 同为 linux 内核提供的动态追踪工具&#xff0c;其中 ftrace 侧重于事件跟踪和内核行为的实时分析&#xff0c;perf 更侧重于性能分析和事件统计&#xff0c;与…

ROS摄像机标定

文章目录 一、环境准备二、摄像头标定2.1 为什么要标定2.2 标定前准备2.2.1 标定板2.2.2 摄像头调焦 2.3 开始标定2.4 测试标定结果 总结参考资料 一、环境准备 安装usb_cam相机驱动 sudo apt-get install ros-noetic-usb-cam 安装标定功能包 sudo apt-get install ros-noet…