首页 > 代码库 > Pig优化之路之巧用Macro

Pig优化之路之巧用Macro

问题:

   去年用Pig进行了一系列报表和ETL的开发,感觉Pig很不错,没有Hive的娇贵,又比粗糙的MapReduce来的精巧,很称手。新年正好涉及以前的程序调整,借此之机,对Pig写的脚本进行了优化。毕竟,越用越熟,越能发现Pig的魅力。

    在整理以前的Pig程序里,发现了一个问题,就是pig没有提取数据集大小的功能,所以每次要取数据集条数的工作,总会遗留下如下代码:

curr_cnt = GROUP curr_uids_dis all;
curr_all_ct = FOREACH curr_cnt GENERATE COUNT(curr_uids_dis.uid)  ;

  其实上面代码的作用就是取出curr_uids_dis数据集的记录条数。但无奈以前对对pig知之甚少,只能遇河搭桥。河过多了,不同的桥也架多了,导致代码非常臃肿。

怎么办?

  这就要深挖一下Pig的语法了,在Pig中,有一个非常有用的宏定义功能。先说简单的,直接关联一个UDF的,语法如下:

DEFINE DataTypeValidationUDF com.validation.DataTypeValidationUDF(); --相当于定义了一个macro DataTypeValidationUDF

以后使用的时候,就直接

DealData = http://www.mamicode.com/DataTypeValidationUDF(claim_amount) ;
当然,如果要自定义一个复杂的处理宏,就可以这么来,语法如下:


DEFINE func1(LOGS) returns numerical_row{ --定义返回值
   --处理逻辑
  $numerical_row =  $LOGS ; --返回值赋值,注意,参数引用要加$
};

这样,办法就来了,我们可以把求数据集条数的语句做一个封装。以后只要调用这个macro就可以了。

/*
Define the macro, specify the input parameters and the return value
*/
DEFINE getDataSize(LOGS) returns numerical_row{
  $numerical_row =  FOREACH (GROUP $LOGS ALL) GENERATE COUNT_STAR($LOGS); --求出数据集的条数
};


但按照我们有追求的程序猿来说,还想干的更完美,我们想把所有的宏都封装到一个文件里,然后在相关程序里引用后再调用。

问题来了,如何做?我们又翻开Pig的语法,开始挖掘。

正好,Pig有这个功能,语法如下:

/*
Import macro defined in the file util.pig
*/
IMPORT '/xxx/xxx/util.pig';

好了,知道如何打造我们的工具库后,我们程序可以这么来写了。

REGISTER 'piggybank.jar';
IMPORT '/xx/util.pig';
LOGS = LOAD  '/in_off/tree_2013/*' USING   PigStorage('\t') as (uid) ;
ret =  getDataSize(LOGS) ;
dump ret;

然后,我们的util.pig清单如下

/*
util.pig place all util macro
*/
DEFINE getDataSize(LOGS) returns numerical_row{
  $numerical_row =  FOREACH (GROUP $LOGS ALL) GENERATE COUNT_STAR($LOGS); --求出数据集的条数
};

以后,我们可以在这里定义所有的工具宏了。

貌似都完成了,但完美的程序猿发现,好像还是有个东西挺别扭。

如果有多个pig文件要import,那同样路径得写好多个啊,浪费。

Pig语法又来了,可以设置Pig的文件包含路径。

set pig.import.search.path '/xxx/xxxx';

这样优化后的总体程序是:

REGISTER 'piggybank.jar';

set pig.import.search.path '/xxx/xxxx';
IMPORT 'util.pig';
LOGS = LOAD  '/in_off/tree_2013/*' USING   PigStorage('\t') as (uid) ;
ret =  getDataSize(LOGS) ;
dump ret;





Pig优化之路之巧用Macro