数据库拆分3--使用sharding-jdbc 子查询注意事项

news2025/2/23 1:52:33

最近在使用sharding-jdbc来改造项目的时候遇到了一些问题,主要是有关子查询的,记录一下。

在某一个库中新建两张表

CREATE TABLE `user_t` (
  `user_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(8) DEFAULT NULL,
  PRIMARY KEY (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1601873255239520258 DEFAULT CHARSET=utf8;

CREATE TABLE `log_t` (
  `id` bigint(20) NOT NULL,
  `user_id` bigint(20) DEFAULT NULL,
  `log_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

模拟了一段子查询sql

<select id="findUserByLog2" resultMap="BaseResultMap">
   SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE log_date > '2022-12-13') and name = 'zhangsan'
</select>

配置文件如下:

server.servlet.context-path=/mutildb


mybatis-plus.configuration.log-impl = org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.root=DEBUG


#shardingjdbc
spring.shardingsphere.datasource.names=wim-user,wim-order

spring.shardingsphere.datasource.wim-user.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.wim-user.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.wim-user.url=jdbc:mysql://127.0.0.1:3306/wim-user?serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.wim-user.username=root
spring.shardingsphere.datasource.wim-user.password=123456

spring.shardingsphere.datasource.wim-order.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.wim-order.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.wim-order.url=jdbc:mysql://127.0.0.1:3306/wim-order?serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.wim-order.username=root
spring.shardingsphere.datasource.wim-order.password=123456

spring.shardingsphere.sharding.tables.user_t.actual-data-nodes=wim-user.user_t
spring.shardingsphere.sharding.tables.log_t.actual-data-nodes=wim-user.log_t

spring.shardingsphere.sharding.tables.user_t.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.user_t.table-strategy.inline.algorithm-expression=user_t

spring.shardingsphere.sharding.tables.log_t.table-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.tables.log_t.table-strategy.inline.algorithm-expression=log_t


spring.shardingsphere.sharding.default-data-source-name=wim-order
spring.shardingsphere.props.sql.show=true
spring.main.allow-bean-definition-overriding=true

调用发现报错如下:

Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e4f7a0d] was not registered for synchronization because synchronization is not active
2022-12-15 21:09:41.574 DEBUG 20200 --- [nio-8080-exec-2] o.s.jdbc.datasource.DataSourceUtils      : Fetching JDBC Connection from DataSource
JDBC Connection [org.apache.shardingsphere.shardingjdbc.jdbc.core.connection.ShardingConnection@208881b4] will not be managed by Spring
==>  Preparing: SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE log_date > '2022-12-13') and name = 'zhangsan'
==> Parameters: 
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e4f7a0d]
2022-12-15 21:09:47.028 DEBUG 20200 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Failed to complete request: org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalStateException: Must have sharding column with subquery.
### The error may exist in file [D:\code\study\muitlDataSource\target\classes\mapper\UserMapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE log_date > '2022-12-13') and name = 'zhangsan'
### Cause: java.lang.IllegalStateException: Must have sharding column with subquery.
2022-12-15 21:09:47.030 ERROR 20200 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/mutildb] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error querying database.  Cause: java.lang.IllegalStateException: Must have sharding column with subquery.
### The error may exist in file [D:\code\study\muitlDataSource\target\classes\mapper\UserMapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE log_date > '2022-12-13') and name = 'zhangsan'
### Cause: java.lang.IllegalStateException: Must have sharding column with subquery.] with root cause

java.lang.IllegalStateException: Must have sharding column with subquery.
	at com.google.common.base.Preconditions.checkState(Preconditions.java:173) ~[guava-18.0.jar:na]
	at org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter.checkSubqueryShardingValues(ParsingSQLRouter.java:136) ~[sharding-core-route-4.0.0-RC1.jar:4.0.0-RC1]
	at org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter.route(ParsingSQLRouter.java:103) ~[sharding-core-route-4.0.0-RC1.jar:4.0.0-RC1]
	at org.apache.shardingsphere.core.route.PreparedStatementRoutingEngine.route(PreparedStatementRoutingEngine.java:66) ~[sharding-core-route-4.0.0-RC1.jar:4.0.0-RC1]
	at org.apache.shardingsphere.core.PreparedQueryShardingEngine.route(PreparedQueryShardingEngine.java:60) ~[sharding-core-entry-4.0.0-RC1.jar:4.0.0-RC1]
	at org.apache.shardingsphere.core.BaseShardingEngine.shard(BaseShardingEngine.java:64) ~[sharding-core-entry-4.0.0-RC1.jar:4.0.0-RC1]
	at org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingPreparedStatement.shard(ShardingPreparedStatement.java:224) ~[sharding-jdbc-core-4.0.0-RC1.jar:4.0.0-RC1]
	at org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingPreparedStatement.execute(ShardingPreparedStatement.java:170) ~[sharding-jdbc-core-4.0.0-RC1.jar:4.0.0-RC1]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_272]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_272]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_272]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_272]
	at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59) ~[mybatis-3.5.9.jar:3.5.9]
	at com.sun.proxy.$Proxy74.execute(Unknown Source) ~[na:na]
	at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:64) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:79) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:63) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:325) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:89) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:151) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:145) ~[mybatis-3.5.9.jar:3.5.9]
	at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:140) ~[mybatis-3.5.9.jar:3.5.9]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_272]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_272]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_272]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_272]
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:427) ~[mybatis-spring-2.0.6.jar:2.0.6]
	at com.sun.proxy.$Proxy58.selectList(Unknown Source) ~[na:na]
	at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224) ~[mybatis-spring-2.0.6.jar:2.0.6]
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForMany(MybatisMapperMethod.java:166) ~[mybatis-plus-core-3.5.1.jar:3.5.1]
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:77) ~[mybatis-plus-core-3.5.1.jar:3.5.1]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) ~[mybatis-plus-core-3.5.1.jar:3.5.1]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) ~[mybatis-plus-core-3.5.1.jar:3.5.1]
	at com.sun.proxy.$Proxy62.findUserByLog2(Unknown Source) ~[na:na]
	at com.chen.rest.UserRest.queryUserByLog2(UserRest.java:25) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_272]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_272]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_272]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_272]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]

主要报错:Must have sharding column with subquery  顾名思义 子查询必须得有分片键

看了一下源码:

public SQLRouteResult route(String logicSQL, List<Object> parameters, SQLStatement sqlStatement) {
        Optional<GeneratedKey> generatedKey = sqlStatement instanceof InsertStatement ? GeneratedKey.getGenerateKey(this.shardingRule, parameters, (InsertStatement)sqlStatement) : Optional.absent();
        SQLRouteResult result = new SQLRouteResult(sqlStatement, (GeneratedKey)generatedKey.orNull());
        OptimizeResult optimizeResult = OptimizeEngineFactory.newInstance(this.shardingRule, sqlStatement, parameters, (GeneratedKey)generatedKey.orNull()).optimize();
        if (generatedKey.isPresent()) {
            this.setGeneratedKeys(result, (GeneratedKey)generatedKey.get());
        }

        boolean needMerge = false;
        if (sqlStatement instanceof SelectStatement) {
            needMerge = this.isNeedMergeShardingValues((SelectStatement)sqlStatement);
        }

        if (needMerge) {
            this.checkSubqueryShardingValues(sqlStatement, optimizeResult.getShardingConditions());
            this.mergeShardingValues(optimizeResult.getShardingConditions());
        }

        RoutingResult routingResult = RoutingEngineFactory.newInstance(this.shardingRule, this.shardingMetaData.getDataSource(), sqlStatement, optimizeResult).route();
        if (sqlStatement instanceof SelectStatement && null != ((SelectStatement)sqlStatement).getLimit() && !routingResult.isSingleRouting()) {
            result.setLimit(this.getProcessedLimit(parameters, (SelectStatement)sqlStatement));
        }

        if (needMerge) {
            Preconditions.checkState(1 == routingResult.getTableUnits().getTableUnits().size(), "Must have one sharding with subquery.");
        }

        result.setRoutingResult(routingResult);
        result.setOptimizeResult(optimizeResult);
        return result;
    }
checkSubqueryShardingValues
 private void checkSubqueryShardingValues(SQLStatement sqlStatement, ShardingConditions shardingConditions) {
        Iterator var3 = sqlStatement.getTables().getTableNames().iterator();

        while(var3.hasNext()) {
            String each = (String)var3.next();
            Optional<TableRule> tableRule = this.shardingRule.findTableRule(each);
            if (tableRule.isPresent() && this.shardingRule.isRoutingByHint((TableRule)tableRule.get()) && !HintManager.getDatabaseShardingValues(each).isEmpty() && !HintManager.getTableShardingValues(each).isEmpty()) {
                return;
            }
        }

        Preconditions.checkState(null != shardingConditions.getShardingConditions() && !shardingConditions.getShardingConditions().isEmpty(), "Must have sharding column with subquery.");
        if (shardingConditions.getShardingConditions().size() > 1) {
            Preconditions.checkState(this.isSameShardingCondition(shardingConditions), "Sharding value must same with subquery.");
        }

    }

可知 如果子查询没有分片键 则会报错:

Must have sharding column with subquery.

如果子查询分片键和主查询分片键不一致  也会报错:

Sharding value must same with subquery.

因此在sharding-jdbc中使用子查询条件是非常有限制的,子查询查询条件必须待分片键 并且和主查询得保持一直。

sql改写如下:

<select id="findUserByLog" resultMap="BaseResultMap">
		SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE user_id = 1) and name = 'zhangsan'
	</select>
2022-12-15 21:21:22.791 DEBUG 20200 --- [alina-utility-2] org.apache.catalina.session.ManagerBase  : Start expire sessions StandardManager at 1671110482790 sessioncount 0
2022-12-15 21:21:23.365 DEBUG 20200 --- [alina-utility-2] org.apache.catalina.session.ManagerBase  : End expire sessions StandardManager processingTime 1 expired sessions: 0
2022-12-15 21:21:23.366  INFO 20200 --- [nio-8080-exec-4] ShardingSphere-SQL                       : Rule Type: sharding
2022-12-15 21:21:23.366  INFO 20200 --- [nio-8080-exec-4] ShardingSphere-SQL                       : Logic SQL: SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE user_id = 1) and name = 'zhangsan'
2022-12-15 21:21:23.366  INFO 20200 --- [nio-8080-exec-4] ShardingSphere-SQL                       : SQLStatement: SelectStatement(super=DQLStatement(super=AbstractSQLStatement(type=DQL, tables=Tables(tables=[Table(name=user_t, alias=Optional.absent()), Table(name=log_t, alias=Optional.absent())]), routeConditions=Conditions(orCondition=OrCondition(andConditions=[AndCondition(conditions=[Condition(column=Column(name=user_id, tableName=user_t), operator=EQUAL, compareOperator==, positionValueMap={0=1}, positionIndexMap={})]), AndCondition(conditions=[Condition(column=Column(name=user_id, tableName=user_t), operator=EQUAL, compareOperator==, positionValueMap={0=1}, positionIndexMap={})])])), encryptConditions=Conditions(orCondition=OrCondition(andConditions=[])), sqlTokens=[TableToken(tableName=user_t, quoteCharacter=NONE, schemaNameLength=0), TableToken(tableName=log_t, quoteCharacter=NONE, schemaNameLength=0)], parametersIndex=0, logicSQL=SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE user_id = 1) and name = 'zhangsan')), containStar=true, firstSelectItemStartIndex=7, selectListStopIndex=7, groupByLastIndex=0, items=[StarSelectItem(owner=Optional.absent())], groupByItems=[], orderByItems=[], limit=null, subqueryStatement=null, subqueryStatements=[], subqueryConditions=[OrCondition(andConditions=[AndCondition(conditions=[Condition(column=Column(name=user_id, tableName=user_t), operator=EQUAL, compareOperator==, positionValueMap={0=1}, positionIndexMap={})])])])
2022-12-15 21:21:23.366  INFO 20200 --- [nio-8080-exec-4] ShardingSphere-SQL                       : Actual SQL: wim-user ::: SELECT * FROM user_t WHERE user_id in (SELECT user_id FROM log_t WHERE user_id = 1) and name = 'zhangsan'
2022-12-15 21:21:23.376 DEBUG 20200 --- [nio-8080-exec-4] o.a.c.loader.WebappClassLoaderBase       :     findClass(com.mysql.jdbc.MySQLConnection)
2022-12-15 21:21:23.377 DEBUG 20200 --- [nio-8080-exec-4] o.a.c.loader.WebappClassLoaderBase       :     --> Returning ClassNotFoundException
2022-12-15 21:21:23.381  WARN 20200 --- [nio-8080-exec-4] c.a.druid.pool.DruidAbstractDataSource   : discard long time none received connection. , jdbcUrl : jdbc:mysql://127.0.0.1:3306/wim-user?serverTimezone=UTC&useSSL=false, version : 1.2.8, lastPacketReceivedIdleMillis : 706768
2022-12-15 21:21:23.381 DEBUG 20200 --- [nio-8080-exec-4] com.alibaba.druid.pool.DruidDataSource   : skip not validate connection.
<==      Total: 0
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@676a183f]

此时sql正常运行。

查看一下官方文档:

子查询 子查询和外层查询同时指定分片键,且分片键的值保持一致时,由内核提供稳定支持。

例如: SELECT * FROM (SELECT * FROM t_order WHERE order_id = 1) o WHERE o.order_id = 1;

用于分页的子查询,由内核提供稳定支持。

例如: SELECT * FROM (SELECT row_.*, rownum rownum_ FROM (SELECT * FROM t_order) row_ WHERE rownum ?;

子查询和外层查询未同时指定分片键,或分片键的值不一致时,由 Federation 执行引擎提供支持。

例如:

SELECT * FROM (SELECT * FROM t_order) o; SELECT * FROM (SELECT * FROM t_order) o WHERE o.order_id = 1;

SELECT * FROM (SELECT * FROM t_order WHERE order_id = 1) o;

SELECT * FROM (SELECT * FROM t_order WHERE order_id = 1) o WHERE o.order_id = 2;

Federation 执行引擎是啥

Apache ShardingSphere 5.0.0 内核优化及升级指南 - 知乎

Federation 执行引擎

Federation 执行引擎是 5.0.0 GA 版内核的又一大亮点功能,目标是支持那些在 4.1.1 GA 版中无法执行的分布式查询语句,例如:跨数据库实例的关联查询及子查询。Federation 执行引擎的出现,使得业务研发人员不必再关心 SQL 的使用范围,能够专注于业务功能开发,减少了业务层面的功能限制。

上图展示了 Federation 执行引擎的处理流程,总体上来看,仍然是遵循着 SQL 解析、SQL 路由、SQL 改写、SQL 执行这几个步骤,唯一的区别是 Federation 执行引擎额外引入了 SQL 优化,对分布式查询语句进行 RBO(Rule Based Optimizer) 和 CBO(Cost Based Optimizer) 优化,从而得到代价最小的执行计划。在 SQL 路由阶段,路由引擎会根据 SQL 语句是否跨多个数据库实例,来决定 SQL 是否通过 Federation 执行引擎来执行。

Federation 执行引擎目前处于快速开发中,仍然需要大量的优化,还是一个实验性的功能,因此默认是关闭的,如果想要体验 Federation 执行引擎,可以通过配置 sql-federation-enabled: true 来开启该功能。

Federation 执行引擎主要用来支持跨多个数据库实例的关联查询和子查询,以及部分内核不支持的聚合查询。下面我们通过具体的场景,来了解下 Federation 执行引擎支持的语句。

  • 跨库关联查询:当关联查询中的多个表分布在不同的数据库实例上时,由 Federation 执行引擎提供支持。

例如,在下面的数据分片配置中,t_order 和 t_order_item 表是多数据节点的分片表,并且未配置绑定表规则,t_user 和 t_user_role 则是分布在不同的数据库实例上的单表。

rules:
- !SHARDING
  tables:
    t_order:
      actualDataNodes: ds_${0..1}.t_order_${0..1}
      tableStrategy:
        standard:
          shardingColumn: order_id
          shardingAlgorithmName: t_order_inline
    t_order_item:
      actualDataNodes: ds_${0..1}.t_order_item_${0..1}
      tableStrategy:
        standard:
          shardingColumn: order_id
          shardingAlgorithmName: t_order_item_inline

由于跨多个数据库实例,下面这些常用的 SQL,会使用 Federation 执行引擎进行关联查询。

SELECT * FROM t_order o INNER JOIN t_order_item i ON o.order_id = i.order_id WHERE o.order_id = 1;
SELECT * FROM t_order o INNER JOIN t_user u ON o.user_id = u.user_id WHERE o.user_id = 1;
SELECT * FROM t_order o LEFT JOIN t_user_role r ON o.user_id = r.user_id WHERE o.user_id = 1;
SELECT * FROM t_order_item i LEFT JOIN t_user u ON i.user_id = u.user_id WHERE i.user_id = 1;
SELECT * FROM t_order_item i RIGHT JOIN t_user_role r ON i.user_id = r.user_id WHERE i.user_id = 1;
SELECT * FROM t_user u RIGHT JOIN t_user_role r ON u.user_id = r.user_id WHERE u.user_id = 1;
  • 子查询:Apache ShardingSphere 的 Simple Push Down 引擎能够支持分片条件一致的子查询,以及路由到单个分片的子查询。对于子查询和外层查询未同时指定分片键,或分片键的值不一致的场景,需要由 Federation 执行引擎来提供支持。

下面展示了一些由 Federation 执行引擎支持的子查询场景:

SELECT * FROM (SELECT * FROM t_order) o;
SELECT * FROM (SELECT * FROM t_order) o WHERE o.order_id = 1;
SELECT * FROM (SELECT * FROM t_order WHERE order_id = 1) o;
SELECT * FROM (SELECT * FROM t_order WHERE order_id = 1) o WHERE o.order_id = 2;
  • 聚合查询:对于 Apache ShardingSphere Simple Push Down 引擎暂不支持的一些聚合查询,我们也同样通过 Federation 执行引擎提供了支持。
SELECT user_id, SUM(order_id) FROM t_order GROUP BY user_id HAVING SUM(order_id) > 10;
SELECT (SELECT MAX(user_id) FROM t_order) a, order_id FROM t_order;
SELECT COUNT(DISTINCT user_id), SUM(order_id) FROM t_order;

Federation 执行引擎的出现,使得 Apache ShardingSphere 分布式查询能力得到明显增强,未来 Apache ShardingSphere 将持续优化,有效降低 Federation 执行引擎的内存占用,不断提升分布式查询的能力。

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

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

相关文章

世界杯决赛号角吹响!趁周末来搭一套足球3D+AI量化分析系统吧!

2022年卡塔尔世界杯从11月21日开赛至今&#xff0c;即将在12月18日迎来这次赛事的最后高潮。对于大部分热爱世界杯的朋友来说&#xff0c;无论之前是哪队的球迷&#xff0c;现在都在会师决赛的两支队伍上选择站队。从赛事结果看&#xff0c;最终无论哪支队伍夺冠&#xff0c;都…

01背包和完全背包

01背包 最大约数和 题目链接点击这里 题目描述 选取和不超过 SSS 的若干个不同的正整数&#xff0c;使得所有数的约数&#xff08;不含它本身&#xff09;之和最大。 输入格式 输入一个正整数 SSS。 输出格式 输出最大的约数之和。 样例 #1 样例输入 #1 11样例输出 …

有哪些值得推荐的Python学习网站?

我学习的时候&#xff0c;我发现大部分 Python 课程和资源都太通用了。 马上&#xff0c;我想学习如何使用 Python 制作网站。但是 Python 学习资源要我花几个月的时间学习语法&#xff0c;然后才能进入我感兴趣的领域。 这个问题让人感到恐惧和畏惧。我推迟了几个月。每当我…

大学生化妆品网页设计模板代码 化妆美妆网页作业成品 学校美妆官网网页制作模板 学生简单html网站设计成品

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

为什么人家的开源项目文档如此炫酷?原来用的是这款神器

VuePress简介 VuePress是Vue驱动的静态网站生成器。对比我们的Docsify动态生成网站&#xff0c;对SEO更加友好。 使用VuePress具有如下优点&#xff1a; 使用Markdown来写文章&#xff0c;程序员写起来顺手&#xff0c;配置网站非常简洁。 我们可以在Markdown中使用Vue组件&…

所谓工作能力强,其实就这五点

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; #mermaid-svg-YapmQUqJ0V32EFv6 {font-family:"trebuchet ms",ve…

用三台云服务器搭建hadoop完全分布式集群

用三台云服务器搭建hadoop完全分布式集群一、硬件准备&#xff08;一&#xff09;集群配置&#xff08;二&#xff09;集群规划&#xff08;三&#xff09;Hadoop、Zookeeper、Java、CentOS版本二、基础环境配置&#xff08;一&#xff09;关闭防火墙&#xff08;二&#xff09…

[附源码]Python计算机毕业设计SSM基于Java的在线点餐系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

12.15

JSONP 1) JSONP 是什么 JSONP(JSON with Padding)&#xff0c;只支持 get 请求。 2) JSONP 怎么工作的&#xff1f; 在网页有一些标签天生具有跨域能力&#xff0c;比如&#xff1a;img link iframe script。 JSONP 就是利用 script 标签的跨域能力来发送请求的。 3) JSONP …

为什么你的接口性能差,实际原因就在这里?

一、前言这篇文章咱们来聊一下&#xff0c;百亿级别的海量数据场景下还要支撑每秒十万级别的高并发查询&#xff0c;这个架构该如何演进和设计&#xff1f;咱们先来看看目前系统已经演进到了什么样的架构&#xff0c;大家看看下面的图&#xff1a;首先回顾一下&#xff0c;整个…

三、Node.js模块化基础 2.0

在Node.js中&#xff0c;模块分为核心&#xff08;原生&#xff09;模块和文件&#xff08;自定义&#xff09;模块&#xff0c;核心模块就是Node.js自带的模块&#xff0c;而自定义模块则是开发者自定义的模块&#xff1b; 核心模块 核心模块有 os&#xff0c;fs&#xff0c;…

发送给Java应用程序的所有参数都必须是字符串吗?

问&#xff1a;发送给Java应用程序的所有参数都必须是字符串吗&#xff1f; 答&#xff1a; 应用程序在运行时&#xff0c;Java将所有参数存储为字符串。要使用整型或其他非字符串参数&#xff0c;必须将其进行转换&#xff0c; 问&#xff1a;既然applet是在Web页面中运行&…

大一作业HTML网页作业:中华传统文化题材网页设计5页(纯html+css实现)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

HTML期末作业,基于html实现中国脸谱传统文化网站设计(5个页面)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

Scrapy_redis分布式原理

今天分享一下Scrapy_redis分布式原理&#xff1a; 1 scrapy_redis是什么 Scrapy_redis &#xff1a; Redis-based components for Scrapy. Github地址&#xff1a;<https://github.com/rmax/scrapy-redis> 在这个地址中存在三个demo&#xff0c;后续我们对scrapy_redi…

大学生简单环保环境静态HTML网页设计作品 DIV布局环境介绍网页模板代码 DW学生环境网站制作成品下载 HTML5期末大作业

&#x1f380; 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

2022_TIP_DSNet

Boosting RGB-D Saliency Detection by Leveraging Unlabeled RGB Images 通过利用未标记的RGB图像来增强rgb-d显着性检测 1. 动机 1) 用于监督学习的像素级注释既昂贵又耗时。 2) 与RGB图像相比&#xff0c;成对的rgb-d图像更难以收集。 2. 解决方法 提出 Dual-Semi RG…

[附源码]Python计算机毕业设计Django景区直通车服务系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

智能人机交互

前言 随着移动机器人越来越多地走向实 际应用&#xff0c;需要提高机器人与人类之 间的协同水平&#xff0c;实现机器人与人类的共融。 一、人机交互的三个级别 二、火星车的遥操作控制 火星车的遥操作控制&#xff08;超大时延&#xff09;&#xff1a;地面团队将命令序列发至…

Linux | 网络概念理解 | 对网络的初识

文章目录重新看待计算机体系结构软件分层的思想网络中的分层协议的理解局域网的理解MAC地址 && IP地址报头的作用端口号&#xff08;port&#xff09;重新看待计算机体系结构 计算机由硬件组成&#xff0c;而不同硬件之间要怎么通信&#xff0c;或者说要怎么进行数据的…