sharding-jdbc多库多表路由sql
本文转自“天河聊技术”微信公众号微信
找到这个类com.dangdang.ddframe.rdb.sharding.routing.PreparedStatementRoutingEngineapp
找到这里分布式
/** * SQL路由. * 当第一次路由时进行SQL解析,以后的路由复用第一次的解析结果. * * @param parameters SQL中的参数 * @return 路由结果 */ public SQLRouteResult route(final List<Object> parameters) {//sql路由业务方法 if (null == sqlStatement) { sqlStatement = sqlRouter.parse(logicSQL, parameters.size()); } return sqlRouter.route(logicSQL, parameters, sqlStatement); }
return sqlRouter.route(logicSQL, parameters, sqlStatement);
@Override public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) { final Context context = MetricsContext.start("Route SQL"); SQLRouteResult result = new SQLRouteResult(sqlStatement); // 若是是insert语句去生成分布式逐渐的逻辑 if (sqlStatement instanceof InsertStatement && null != ((InsertStatement) sqlStatement).getGeneratedKey()) { processGeneratedKey(parameters, (InsertStatement) sqlStatement, result); } RoutingResult routingResult = route(parameters, sqlStatement);
RoutingResult routingResult = route(parameters, sqlStatement);
private RoutingResult route(final List<Object> parameters, final SQLStatement sqlStatement) { Collection<String> tableNames = sqlStatement.getTables().getTableNames(); RoutingEngine routingEngine; // 若是表集合是1,或者是绑定表路由就走简单路由规则 if (1 == tableNames.size() || shardingRule.isAllBindingTables(tableNames)) { routingEngine = new SimpleRoutingEngine(shardingRule, parameters, tableNames.iterator().next(), sqlStatement);//单表路由 } else { // TODO 可配置是否执行笛卡尔积 routingEngine = new ComplexRoutingEngine(shardingRule, parameters, tableNames, sqlStatement); } return routingEngine.route();//tianhe TODO 笛卡尔积 }
进入到这个方法com.dangdang.ddframe.rdb.sharding.routing.type.complex.ComplexRoutingEngine.route()ide
@Override public RoutingResult route() { Collection<RoutingResult> result = new ArrayList<>(logicTables.size()); Collection<String> bindingTableNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); for (String each : logicTables) { // 根据逻辑表查找分片规则 Optional<TableRule> tableRule = shardingRule.tryFindTableRule(each); if (tableRule.isPresent()) { // 若是绑定表名不包含逻辑表走简单路由 if (!bindingTableNames.contains(each)) { result.add(new SimpleRoutingEngine(shardingRule, parameters, tableRule.get().getLogicTable(), sqlStatement).route()); } // 根据逻辑表找绑定表规则配置,若是有走绑定表规则配置路由 Optional<BindingTableRule> bindingTableRule = shardingRule.findBindingTableRule(each); if (bindingTableRule.isPresent()) { bindingTableNames.addAll(Lists.transform(bindingTableRule.get().getTableRules(), new Function<TableRule, String>() { @Override public String apply(final TableRule input) { return input.getLogicTable(); } })); } } } log.trace("mixed tables sharding result: {}", result); if (result.isEmpty()) { throw new ShardingJdbcException("Cannot find table rule and default data source with logic tables: '%s'", logicTables); } if (1 == result.size()) { return result.iterator().next(); } // 建立混合多库表路由结果 return new CartesianRoutingEngine(result).route(); }
return new CartesianRoutingEngine(result).route();
笛卡尔积路由引擎ui
/** * 笛卡尔积的库表路由. * * @author zhangliang */ @RequiredArgsConstructor @Slf4j public final class CartesianRoutingEngine implements RoutingEngine { // 路由结果 private final Collection<RoutingResult> routingResults;
返回到这里orm
@Override public CartesianRoutingResult route() { // 建立笛卡尔积路由对象 CartesianRoutingResult result = new CartesianRoutingResult(); // 遍历数据源和逻辑表集合的映射关系 for (Entry<String, Set<String>> entry : getDataSourceLogicTablesMap().entrySet()) { // 获取物理表集合 List<Set<String>> actualTableGroups = getActualTableGroups(entry.getKey(), entry.getValue()); // 根据数据源和物理表集合获取具体的执行单元 List<Set<TableUnit>> tableUnitGroups = toTableUnitGroups(entry.getKey(), actualTableGroups); result.merge(entry.getKey(), getCartesianTableReferences(Sets.cartesianProduct(tableUnitGroups))); } log.trace("cartesian tables sharding result: {}", result); return result; }
组装笛卡尔积结果集 Sets.cartesianProduct(tableUnitGroups)
组装笛卡尔积路由组对象
getCartesianTableReferences(Sets.cartesianProduct(tableUnitGroups))
组装笛卡尔积路由结果对象路由
result.merge
以上介绍了多库表、笛卡尔积路由。get
向上返回到这里
@Override public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) { final Context context = MetricsContext.start("Route SQL"); SQLRouteResult result = new SQLRouteResult(sqlStatement); // 若是是insert语句去生成分布式逐渐的逻辑 if (sqlStatement instanceof InsertStatement && null != ((InsertStatement) sqlStatement).getGeneratedKey()) { processGeneratedKey(parameters, (InsertStatement) sqlStatement, result); } // 进行sql路由返回路由结果 RoutingResult routingResult = route(parameters, sqlStatement); SQLRewriteEngine rewriteEngine = new SQLRewriteEngine(shardingRule, logicSQL, sqlStatement); boolean isSingleRouting = routingResult.isSingleRouting(); if (sqlStatement instanceof SelectStatement && null != ((SelectStatement) sqlStatement).getLimit()) { processLimit(parameters, (SelectStatement) sqlStatement, isSingleRouting); } SQLBuilder sqlBuilder = rewriteEngine.rewrite(!isSingleRouting); if (routingResult instanceof CartesianRoutingResult) { for (CartesianDataSource cartesianDataSource : ((CartesianRoutingResult) routingResult).getRoutingDataSources()) { for (CartesianTableReference cartesianTableReference : cartesianDataSource.getRoutingTableReferences()) { result.getExecutionUnits().add(new SQLExecutionUnit(cartesianDataSource.getDataSource(), rewriteEngine.generateSQL(cartesianTableReference, sqlBuilder))); } } } else { for (TableUnit each : routingResult.getTableUnits().getTableUnits()) { result.getExecutionUnits().add(new SQLExecutionUnit(each.getDataSourceName(), rewriteEngine.generateSQL(each, sqlBuilder))); } } MetricsContext.stop(context); if (showSQL) { SQLLogger.logSQL(logicSQL, sqlStatement, result.getExecutionUnits(), parameters); } return result; }
后面的是sql重写的部分下次介绍。
说到最后
以上是混合多库多表路由源码解析,仅供参考。