Sharding-JDBC源码解析(六)结果归并

Sharding-JDBC源码解析(一)整体流程-CSDN博客

Sharding-JDBC源码解析(二)SQL解析-CSDN博客

Sharding-JDBC源码解析(三)SQL路由-CSDN博客

Sharding-JDBC源码解析(四)SQL改写-CSDN博客

Sharding-JDBC源码解析(五)SQL执行-CSDN博客

Sharding-JDBC源码解析(六)结果归并-CSDN博客

目录

一、整体概述

二、详细流程

1.整体流程

2.排序归并

2-1.初始变化排序

2-2.重排序

3.分页归并

3-1.offset处理

3-2.limit处理


一、整体概述

结果归并就是将从各个数据节点获取的多数据结果集,组合成为一个结果集。

ShardingSphere 支持的结果归并从功能上分为遍历、排序、分组、分页和聚合 5 种类型,它们是组合而非互斥的关系。 从结构划分,可分为流式归并、内存归并和装饰者归并。流式归并和内存归并是互斥的,装饰者归并可以在流式归并和内存归并之上做进一步的处理。

二、详细流程

归并引擎 :: ShardingSphere

1.整体流程

    public ResultSet getResultSet() throws SQLException {
        // 获取各个执行单元返回的结果集
        List<ResultSet> resultSets = getResultSets();
        // 根据sql选择对应的归并引擎主要有遍历、排序、分组、分页和聚合 5 种类型
        MergedResult mergedResult = mergeQuery(getQueryResults(resultSets));
        currentResultSet = new ShardingSphereResultSet(resultSets, mergedResult, this, executionContext);
        return currentResultSet;
    }

2.排序归并

排序归并从结构上看属于流式归并,所以并不需要一次性将所有结果加载到内存中,而是通过一个优先级队列将排序的动作放到每一次获取元素的过程中。

归并引擎 :: ShardingSphere

排序归并流程就是分为两步,一是在构造函数中进行初始化排序,二是在每次获取元素(next方法)后的重排序。

2-1.初始变化排序

代码位于OrderByStreamMergedResult#orderResultSetsToQueue

    private void orderResultSetsToQueue(final List<QueryResult> queryResults, final SelectStatementContext selectStatementContext, final ShardingSphereSchema schema) throws SQLException {
        for (QueryResult each : queryResults) {
            // 因为各个结果集都是有序的,所以比较结果集的头节点便可以确认队列的优先级。
            OrderByValue orderByValue = new OrderByValue(each, orderByItems, selectStatementContext, schema);

            if (orderByValue.next()) {
                orderByValuesQueue.offer(orderByValue);
            }
        }
        setCurrentQueryResult(orderByValuesQueue.isEmpty() ? queryResults.get(0) : orderByValuesQueue.peek().getQueryResult());
    }

2-2.重排序

代码位于OrderByStreamMergedResult#next,其实就是每次获取完一条数据之后,将结果集中剩下的数据重新排序。

    public boolean next() throws SQLException {
        if (orderByValuesQueue.isEmpty()) {
            return false;
        }
        if (isFirstNext) {
            isFirstNext = false;
            return true;
        }
        OrderByValue firstOrderByValue = orderByValuesQueue.poll();
        if (firstOrderByValue.next()) {
            orderByValuesQueue.offer(firstOrderByValue);
        }
        if (orderByValuesQueue.isEmpty()) {
            return false;
        }
        setCurrentQueryResult(orderByValuesQueue.peek().getQueryResult());
        return true;
    }

3.分页归并

分页归并属于装饰者归并,例如在排序归并的基础上做处理。分页归并也是分为两个过程,一是在构造函数中进行偏移量(offset)处理,二是在每次获取元素(next方法)时判断是否超过limit。

3-1.offset处理

代码入口位于LimitDecoratorMergedResult#skipOffset

    private boolean skipOffset() throws SQLException {
        // 跳过不需要的行
        for (int i = 0; i < pagination.getActualOffset(); i++) {
            if (!getMergedResult().next()) {
                return true;
            }
        }
        rowNumber = 0;
        return false;
    }

3-2.limit处理

    public boolean next() throws SQLException {
        // 是否超出limit
        return ++rowNumber <= pagination.getActualRowCount().get() && getMergedResult().next();
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值