前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【死磕Sharding-jdbc】---group by的SQL重写为limit Integer.MAX_VALUE的无奈

【死磕Sharding-jdbc】---group by的SQL重写为limit Integer.MAX_VALUE的无奈

作者头像
用户1655470
发布2018-08-03 11:53:26
1K0
发布2018-08-03 11:53:26
举报
文章被收录于专栏:chenssy

有内涵、有价值的文章第一时间送达!

这篇文章源于【死磕Sharding-jdbc】-----重写的遗留问题,相关sharding-jdbc源码如下:

代码语言:javascript
复制
private void appendLimitRowCount(final SQLBuilder sqlBuilder, final RowCountToken rowCountToken, final int count, final List<SQLToken> sqlTokens, final boolean isRewrite) {    SelectStatement selectStatement = (SelectStatement) sqlStatement;    Limit limit = selectStatement.getLimit();    if (!isRewrite) {        ... ...    } else if ((!selectStatement.getGroupByItems().isEmpty() || !selectStatement.getAggregationSelectItems().isEmpty()) && !selectStatement.isSameGroupByAndOrderByItems()) {        // 如果要重写sql中的limit的话,且sql中有group by或者有group by & order by,例如"select user_id, sum(score) from t_order group by user_id order by sum(score) desc limit 5",那么limit 5需要重写为limit Integer.MAX_VALUE,原因接下来分析        sqlBuilder.appendLiterals(String.valueOf(Integer.MAX_VALUE));    } else {        ... ...    }    ... ...}

构造数据

为了解释为什么limit rowCount中的rowCount需要重写为Integer.MAX_VALUE,需要先构造一些数据,如下图所示:

如果不分库分表的话,数据如下图所示:

执行SQL

假定执行如下SQL:

代码语言:javascript
复制
select user_id, sum(score) from t_order group by user_id order by sum(score) desc limit 5;

结果如下所示:

假定 selectuser_id,sum(score)fromt_ordergroupbyuser_id orderbysum(score)desc limit5;这个SQL不重写为 limit0,Integer.MAX_VALUE,那么 t_order_0t_order_1的结果分别如下; t_order_0的结果:

t_order_1的结果:

路由到两个表的执行结果归并后的结果如下:

分析

根据执行结果可知,主要差异在于,真实结果有userid为20,21的数据。我们在看一下 t_order_0t_order_1两个分表中这两个userid的数据有什么特殊之处:

t_order_1这个分表中,由于userid为20,21的score值在TOP 5以外。但是合并 t_order_0t_order_1两个分表的结果,userid为20的sum(score)能够排在第一(18+18=36);所以,如果group by这类的SQL不重写为 limit0,Integer.MAX_VALUE的话,会导致结果有误。所以sharding-jdbc的源码必须要这样重写,没有其他办法!

延伸

事实上不只是sharding-jdbc,任何有sharding概念的中间件例如es,都要这么处理,因为sharding后数据处理的流程几乎都要经过解析->重写->路由->执行->结果归并这几个阶段;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-07-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java技术驿站 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 构造数据
  • 执行SQL
  • 分析
  • 延伸
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档