sybn sybn-util 项目说明文档 - 基于java的跨数据库联合查询

SqlPartFieldListExplain 查询计划

2020-01-01
sybn

简介

本文讨论 sql 单表执行计划工具类 SqlPartFieldListExplain.

此工具类会将单行 sql 中的内容区分出不同的执行优先级.

比如: (sum(a)/sum(b)) as c, 应该先执行 sum(a) 和 sum(b), 延后执行除法.

需求

日常的查询语句中 select 部分不同字段之间是有执行优先级差异的.

在暂时不考虑 where 和 having 的情况下, 比如:

SELECT a, cast(b as SIGNED) as c, (a+1) as d, sum(c) as e, (1/e) as f, (sum(g)/sum(h)) as i from table group by d

其执行计划为:

  • 步骤1: 获取基础字段

SELECT a, b, g, h

FROM table

蓝色的 a 为 直接指定的字段;

红色的 b,g,h 为函数中引用的字段;

c, d, e, f, i 为计算后派生出来的字段当前阶段不需要处理

  • 步骤2: 执行 group by 前置计算, 互相依赖的参数按顺序执行

SELECT a, cast(b as SIGNED) as c, (a+1) as d, g, h

FROM 上一步结果

其中蓝色的为 直接指定的部分;

红色的为函数中引用的字段;

e, f, i 为计算后派生出来的字段当前阶段不需要处理

  • 步骤3: 执行 group by

SELECT max(a) as a, max(c) as c, d, sum(c) as e, sum(g) as __sum_g, sum(h) as __sum_h

FROM 上一步结果

GROUP BY d

a, c 为 未被聚合函数和 group by 属性命中的游离字段. mysql中对游离字段不承诺返回值运算方式,因此我们用max统一处理

__sum_g, __sum_h 为派生出来的临时字段, 仅在 group by 阶段使用, 不出现在最终的返回值中

  • 步骤4: 执行 group by 后置计算, 互相依赖的参数按顺序执行

SELECT a, c, d, e, (1/e) as f, (__sum_g/__sum_h) as i

FROM 上一步结果

i 为组装历史字段得到

SqlPartFieldListExplain 实现

a. 将中 SqlPartFieldList 的基础字段记录在 dependFields 中, 用于支持步骤1

b. 将中 SqlPartFieldList 中的复合字段拆分为 originalFields, temporaryFields, compositeFields

分类 说明 sql来源 sql输出
originalFields sql语句中显式指定的字段及其函数(其参数不包含聚合成分) a, cast(b as SIGNED) as c, (a+1) as d, sum(c) as e  
temporaryFields sql语句中隐式包含的聚合函数 (sum(g)/sum(h)) as i sum(g) as __sum_g, sum(h) as __sum_h
compositeFields sql语句中显式指定的字段及其函数(其参数中的聚合成分被替换为temporaryFields的字段名) (1/e) as f, (sum(g)/sum(h)) as i (1/e) as f, (__sum_g/__sum_h) as i

c. 将 originalFields, temporaryFields, compositeFields 从新组合为执行计划

步骤 说明 成分 sql输出
步骤1 获取基础字段 dependFields, 表名 SELECT dependFields FROM 表名
步骤2,步骤3 执行 group by及其前置函数 originalFields, temporaryFields SELECT originalFields, temporaryFields FROM 上一步结果
步骤4 执行 group by 后置计算 originalFields.asFieldName, compositeFields SELECT originalFields.asFieldName, compositeFields FROM 上一步结果

Similar Posts

Comments

暂不开放评论! 可微信联系