MaxCompute重装上阵 第五弹 - SELECT TRANSFORM

MaxCompute(原ODPS)是阿里云自主研发的具备业界领先水平的分布式大数据处理平台, 尤为在集团内部获得普遍应用,支撑了多个BU的核心业务。 MaxCompute除了持续优化性能外,也致力于提高SQL语言的用户体验和表达能力,提升广大ODPS开发者的生产力。php

MaxCompute基于ODPS2.0新一代的SQL引擎,显著提高了SQL语言编译过程的易用性与语言的表达能力。咱们在此推出MaxCompute(ODPS2.0)重装上阵系列文章html

第一弹 - 善用MaxCompute编译器的错误和警告
第二弹 - 新的基本数据类型与内建函数
第三弹 - 复杂类型
第四弹 - CTE,VALUES,SEMIJOINjava

上次向您介绍了CTE,VALUES,SEMIJOIN,本篇向您介绍MaxCompute对其余脚本语言的支持 - SELECT TRANSFORM。python

  • 场景1
    sql

    个人系统要迁移到MaxCompute平台上,系统中原来有不少功能是使用脚原本完成的,包括python,shell,ruby等脚本。 要迁移到MaxCompute上,我须要把这些脚本所有都改形成UDF/UDAF/UDTF。改造过程不只须要耗费时间人力,还须要作一遍又一遍的测试,从而保证改形成的udf和原来的脚本在逻辑上是等价的。我但愿能有更简单的迁移方式。

  • 场景2
    shell

    SQL比较擅长的是集合操做,而我须要作的事情要对一条数据作更多的精细的计算,现有的内置函数不能方便的实现我想要的功能,而UDF的框架不够灵活,而且Java/Python我都不太熟悉。相比之下我更擅长写脚本。我就但愿可以写一个脚本,数据全都输入到个人脚本里来,我本身来作各类计算,而后把结果输出。而MaxCompute平台就负责帮我把数据作好切分,让个人脚本可以分布式执行,负责数据的输入表和输出表的管理,负责JOIN,UNION等关系操做就行了。

上述功能可使用SELECT TRANSFORM来实现apache

SELECT TRANSFORM 介绍

此文中采用MaxCompute Studio做展现,首先,
导入测试MaxCompute项目,建立工程
,创建一个新的MaxCompute脚本文件, 以下

5ac16247e0b846b2673b47b462c7d73ac95ecd49

提交做业能够看到执行计划(所有展开后的视图):ruby

9cd7ea0d4e9b11150cbbb81cc9d257da5346338f

Select transform容许sql用户指定在服务器上执行一句shell命令,将上游数据各字段用tab分隔,每条记录一行,逐行输入shell命令的stdin,并从stdout读取数据做为输出,送到下游。Shell命令的本质是调用Unix的一些utility,所以能够启动其余的脚本解释器。包括python,java,php,awk,ruby等。bash

该命令兼容Hive的Transform功能,能够参考Hive的文档。一些须要注意的点以下:
1. Using 子句指定的是要执行的命令,而非资源列表,这一点和大多数的MaxCompute SQL语法不同,这么作是为了和hive的语法保持兼容。
2. 输入从stdin传入,输出从stdout传出;
3. 能够配置分隔符,默认使用 \t 分隔列,用换行分隔行;
4. 能够自定义reader/writer,但用内置的reader/writer会快不少
5. 使用自定义的资源(脚本文件,数据文件等),可使用 set odps.sql.session.resources=foo.sh,bar.txt; 来指定。能够指定多个resource文件,用逗号隔开(所以不容许resource名字中包含逗号和分号)。此外咱们还提供了resources子句,能够在using 子句后面指定 resources 'foo.sh', 'bar.txt' 来指定资源,两种方式是等价的(参考“用odps跑测试”的例子);
6. 资源文件会被下载到执行指定命令的工做目录,可使用文件接口打开./bar.txt文件。服务器

目前odps select transform彻底兼容了hive的语法、功能和行为,包括 input/output row format 以及 reader/writer。Hive上的脚本,大部分能够直接拿来运行,部分脚本只须要通过少量改动便可运行。另外咱们不少功能都用比hive更高执行效率的语言 (C++) 重构,用以优化性能。

应用场景举例

理论上select transform能实现的功能udtf都能实现,可是select transform比udtf要灵活得多。且select transform不只支持java和python,还支持shell,perl等其它脚本和工具。 且编写的过程要简单,特别适合adhoc功能的实现。举几个例子:
1. 无中生有造数据

select transform(script) using 'sh' as (data) from
(
    select 'for i in `seq 1 50`; do echo $i; done' as script
) t;
复制代码

或者使用python

select transform('for i in xrange(1, 51): print i;') using 'python' as (data);
复制代码

上面的语句造出一份有50行的数据表,值是从1到50; 测试时候的数据就能够方便造出来了。功能看似简单,但之前是odps的一个痛点,没有方便的办法造数据,就不方便测试以及初学者的学习和探索。固然这也能够经过udtf来实现,可是须要复杂的流程:进入ide->写udtf->打包->add jar/python->create function->执行->drop function->drop resource。
2. awk 用户会很喜欢这个功能

select transform(*) using "awk '//{print $2}'" as (data) from src;
复制代码

上面的语句仅仅是把value原样输出,可是熟悉awk的用户,今后过上了写awk脚本不写sql的日子
3. 用odps跑测试

select transform(key, value) 
   using 'java -cp a.jar org.junit.runner.JUnitCore MyTestClass' 
   resources 'a.jar' 
from testdata;
复制代码

或者

set odps.sql.session.resources=a.jar;
select transform(key, value) 
   using 'java -cp a.jar org.junit.runner.JUnitCore MyTestClass' 
from testdata;
复制代码

这个例子是为了说明,不少java的utility能够直接拿来运行。java和python虽然有现成的udtf框架,可是用select transform编写更简单,而且不须要额外依赖,也没有格式要求,甚至能够实现离线脚本拿来直接就用。
4. 支持其余脚本语言

select transform (key, value) using "perl -e 'while($input = <STDIN>){print $input;}'" from src;
复制代码

上面用的是perl。这其实不只仅是语言支持的扩展,一些简单的功能,awk, python, perl, shell 都支持直接在命令里面写脚本,不须要写脚本文件,上传资源等过程,开发过程更简单。另外,因为目前咱们计算集群上没有php和ruby,因此这两种脚本不支持。
5. 能够串联着用,使用 distribute by和 sort by对输入数据作预处理

select transform(key, value) using 'cmd2' from 
(
    select transform(*) using 'cmd1' from 
    (
        select * from data distribute by col2 sort by col1
    ) t distribute by key sort by value
) t2;
复制代码

或者用map,reduce的关键字会让逻辑显得清楚一些

@a := select * from data distribute by col2 sort by col1;
@b := map * using 'cmd1' distribute by col1 sort by col2 from @a;
reduce * using 'cmd2' from @b;
复制代码

理论上OpenMR的模型均可以映射到上面的计算过程。注意,使用map,reduce,select transform这几个语法其实语义是同样的,用哪一个关键字,哪一种写法,不影响直接过程和结果。

性能

性能上,SELECT TRANSFORM 与UDTF 各有千秋。通过多种场景对比测试,数据量较小时,大多数场景下select transform有优点,而数据量大时UDTF有优点。因为transform的开发更加简便,因此select transform很是适合作adhoc的数据分析。

UDTF的优点:

  1. UDTF是有类型,而Transform的子进程基于stdin/stdout传输数据,全部数据都当作string处理,所以transform多了一步类型转换;
  2. Transform数据传输依赖于操做系统的管道,而目前管道的buffer仅有4KB,且不能设置, transform读/写 空/满 的pipe会致使进程被挂起;
  3. UDTF的常量参数能够不用传输,而Transform没办法利用这个优化。

SELECT TRANSFORM 的优点:

  1. 子进程和父进程是两个进程,而UDTF是单线程的,若是计算占比比较高,数据吞吐量比较小,能够利用服务器的多核特性
  2. 数据的传输经过更底层的系统调用来读写,效率比java高
  3. SELECT TRANSFORM支持的某些工具,如awk,是natvie代码实现的,和java相比理论上可能会有性能优点。

小结

MaxCompute基于ODPS2.0的SQL引擎,提供了SELECT TRANSFORM功能,能够明显简化对脚本代码的引用,与此同时,也提升了性能!咱们推荐您尽可能使用SELECT TRANSFORM。

标注

  • 注一,USING 后面的字符串,在后台是直接起的子进程来调起命令,没有起shell,因此shell的某些语法,如输入输出重定向,管道等是不支持的。若是用户须要能够以 shell 做为命令,真正的命令做为数据输入,参考“无中生有造数据”的例子;
  • 注二,JAVA 和 PYTHON 的实际路径,能够从JAVA_HOME 和 PYTHON_HOME 环境变量中获得做业;


本文做者:阿里云高级技术专家 秋鹏
相关文章
相关标签/搜索