阿飞Javaer,转载请注明原创出处,谢谢!
在5. sharding-jdbc源码之结果合并中已经分析了OrderByStreamResultSetMerger、LimitDecoratorResultSetMerger、IteratorStreamResultSetMerger,查看源码目录下ResultSetMerger的实现类,只剩下GroupByMemoryResultSetMerger和GroupByStreamResultSetMerger两个实现类的分析,接下来根据源码对两者的实现进行剖析;
如何选择
GroupBy有两个ResultSetMerge的实现:GroupByMemoryResultSetMerger和GroupByStreamResultSetMerger,那么如何选择呢?在MergeEngine中有一段这样的代码:
private ResultSetMerger build() throws SQLException {
// 如果有group by或者聚合类型(例如sum, avg等)的SQL条件,就会选择一个GroupBy***ResultSetMerger
if (!selectStatement.getGroupByItems().isEmpty() || !selectStatement.getAggregationSelectItems().isEmpty()) {
// isSameGroupByAndOrderByItems()源码紧随其后
if (selectStatement.isSameGroupByAndOrderByItems()) {
return new GroupByStreamResultSetMerger(columnLabelIndexMap, resultSets, selectStatement);
} else {
return new GroupByMemoryResultSetMerger(columnLabelIndexMap, resultSets, selectStatement);
}
}
if (!selectStatement.getOrderByItems().isEmpty()) {
return new OrderByStreamResultSetMerger(resultSets, selectStatement.getOrderByItems());
}
return new IteratorStreamResultSetMerger(resultSets);
}
// 如果只有group by条件,没有order by,那么isSameGroupByAndOrderByItems()为true,例如:`SELECT o.* FROM t_order o where o.user_id=? group by o.order_id`(因为这种sql会被改写为SELECT o.* , o.order_id AS GROUP_BY_DERIVED_0 FROM t_order_0 o where o.user_id=? group by o.order_id ORDER BY GROUP_BY_DERIVED_0 ASC,即group by和order by完全相同)
public boolean isSameGroupByAndOrderByItems() {
return !getGroupByItems().isEmpty() && getGroupByItems().equals(getOrderByItems());
}
由上段源码分析可知,如果只有group by条件,那么选择GroupByStreamResultSetMerger;那么如果既有group by,又有order by,那么就会选择GroupByStreamResultSetMerger;
接下来分析GroupByStreamResultSetMerger中如何对结果进行group by聚合,假设数据源js_jdbc_0
中实际表t_order_0
和实际表t_order_1
的数据如下:
order_id | user_id | status |
---|---|---|
1000 | 10 | INIT |
1002 | 10 | INIT |
1004 | 10 | VALID |
1006 | 10 | NEW |
1008 | 10 | INIT |
order_id | user_id | status |
---|---|---|
1001 | 10 | NEW |
1003 | 10 | NEW |
1005 | 10 | VALID |
1007 | 10 |