subquery
子查询指一个查询语句嵌套在另一个查询语句内部的查询,在 SELECT 子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表,子查询中常用的操作符有 ANY(SOME)、ALL、IN 和 EXISTS。常见形式如下
数据中间件一般处理subquery思路是拆分SQL语句,先查询内部语句结果作为外部条件继续查询,整体流程类似下图
另外一种处理方式就是确定subquery内部查询与外部查询是否在同一个分片(db)上,如果可以确定这层关系,则可以将SQL直接发送到某个分片上,一般在非代理数据中间件实现中,可以考虑这种方式规避拆分subquery,尤其在oracle嵌套分页查询时需要面临这个问题。
sharding subquery
了解subquery后,我们来看看sharding-JDBC是怎么处理subquery的,希望读者对原理有了解后,能正确使用子查询,首先我们来验证上边这个场景,SQL如下
select * from t_order where order_id in (select order_id from t_order_item where order_name ='zhangsan')
复制代码
执行结果有点出乎意料
java.lang.IllegalStateException: Must have sharding column with subquery.
at com.google.common.base.Preconditions.checkState(Preconditions.java:173)
at org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter.checkSubqueryShardingValues(ParsingSQLRouter.java:111)
at org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter.route(ParsingSQLRouter.java:75)
at org.apache.shardingsphere.core.route.StatementRoutingEngine.route(StatementRoutingEngine.java:56)复制代码
提示我们必须要分片键,我们可以把t_order_item表分片键改为order_name
t_order_item:
actualDataNodes: ds_0.t_order_item
tableStrategy:
inline:
shardingColumn: order_name
algorithmExpression: t_order_item
databaseStrategy:
inline:
shardingColumn: order_name
algorithmExpression: ds_0复制代码
执行结果还是同样的错误,将SQL改写如下
select * from t_order where order_id in (select order_id from t_order_item where order_id =1001)