更新时间:2023-03-17 GMT+08:00

跨源复杂数据的SQL查询优化

场景描述

出于管理和信息收集的需要,企业内部会存储海量数据,包括数目众多的各种数据库、数据仓库等,此时会面临以下困境:数据源种类繁多,数据集结构化混合,相关数据存放分散等,这就导致了跨源复杂查询因传输效率低,耗时长。

当前开源Spark在跨源查询时,只能对简单的filter进行下推,因此造成大量不必要的数据传输,影响SQL引擎性能。针对下推能力进行增强,当前对aggregate、复杂projection、复杂predicate均可以下推到数据源,尽量减少不必要数据的传输,提升查询性能。

目前仅支持JDBC数据源的查询下推,支持的下推模块有aggregate、projection、predicate、aggregate over inner join、aggregate over union all等。为应对不同应用场景的特殊需求,对所有下推模块设计开关功能,用户可以自行配置是否应用上述查询下推的增强。

表1 跨源查询增加特性对比

模块

增强前

增强后

aggregate

不支持aggregate下推

  • 支持的聚合函数为:sum, avg, max, min, count

    例如:select count(*) from table

  • 支持聚合函数内部表达式

    例如:select sum(a+b) from table

  • 支持聚合函数运算,例如:select avg(a) + max(b) from table
  • 支持having下推

    例如:select sum(a) from table where a>0 group by b having sum(a)>10

  • 支持部分函数下推

    支持对abs()、month()、length()等数学、时间、字符串函数进行下推。并且,除了以上内置函数,用户还可以通过SET命令新增数据源支持的函数。

    例如:select sum(abs(a)) from table

  • 支持aggregate之后的limit、order by下推(由于Oracle不支持limit,所以Oracle中limit、order by不会下推)

    例如:select sum(a) from table where a>0 group by b order by sum(a) limit 5

projection

仅支持简单projection下推,例如:select a, b from table

  • 支持复杂表达式下推。

    例如:select (a+b)*c from table

  • 支持部分函数下推,详细参见表下方的说明。

    例如:select length(a)+abs(b) from table

  • 支持projection之后的limit、order by下推。

    例如:select a, b+c from table order by a limit 3

predicate

仅支持运算符左边为列名右边为值的简单filter,例如

select * from table where a>0 or b in (“aaa”, “bbb”)

  • 支持复杂表达数下推

    例如:select * from table where a+b>c*d or a/c in (1, 2, 3)

  • 支持部分函数下推,详细参见表下方的说明。

    例如:select * from table where length(a)>5

aggregate over inner join

需要将两个表中相关的数据全部加载到Spark,先进行join操作,再进行aggregate操作

支持以下几种:

  • 支持的聚合函数为:sum, avg, max, min,count
  • 所有aggregate只能来自同一个表,group by可以来自一个表或者两个表,只支持inner join。

不支持的情形有:

  • 不支持aggregate同时来自join左表和右表的下推。
  • 不支持aggregate内包含运算,如:sum(a+b)。
  • 不支持aggregate运算,如:sum(a)+min(b)。

aggregate over union all

需要将两个表中相关的数据全部加载到Spark,先进行union操作,再进行aggregate操作

支持情况:

支持的聚合函数为:sum, avg, max, min,count

不支持的情况:

  • 不支持aggregate内包含运算,如:sum(a+b)。
  • 不支持aggregate运算,如:sum(a)+min(b)。

注意事项

  • 外部数据源是Hive的场景,通过Spark建的外表无法进行查询。
  • 数据源只支持MySQL和Mppdb。