如何在 Apache Pig 上强制执行正确的数据类型?

Posted

技术标签:

【中文标题】如何在 Apache Pig 上强制执行正确的数据类型?【英文标题】:How can correct data types on Apache Pig be enforced? 【发布时间】:2012-01-12 00:56:12 【问题描述】:

由于数据类型错误,我无法对一组值进行求和。

当我加载行如下所示的 csv 文件时:

6   574 false   10.1.72.23  2010-05-16 13:56:19 +0930   fbcdn.net   static.ak.fbcdn.net 304 text/css    1   /rsrc.php/zPTJC/hash/50l7x7eg.css   http    pwong

使用以下内容:

logs_base = FOREACH raw_logs GENERATE
  FLATTEN(
     EXTRACT(line, '^(\\d+),"(\\d+)","(\\w+)","(\\S+)","(.+?)","(\\S+)","(\\S+)","(\\d+)","(\\S+)","(\\d+)","(\\S+)","(\\S+)","(\\S+)"')
  )
  as (
    account_id: int,
    bytes: long,
    cached: chararray,
    ip: chararray,
    time: chararray,
    domain: chararray,
    host: chararray,
    status: chararray,
    mime_type: chararray,
    page_view: chararray,
    path: chararray,
    protocol: chararray,
    username: chararray
  );

所有字段似乎都加载得很好,并且类型正确,如“describe”命令所示:

grunt> describe logs_base
logs_base: account_id: int,bytes: long,cached: chararray,ip: chararray,time: chararray,domain: chararray,host: chararray,status: chararray,mime_type: chararray,page_view: chararray,path: chararray,protocol: chararray,username: chararray

每当我使用以下方法执行 SUM 时:

bytesCount = FOREACH (GROUP logs_base ALL) GENERATE SUM(logs_base.bytes);

并存储或转储内容,mapreduce 过程失败并出现以下错误:

org.apache.pig.backend.executionengine.ExecException: ERROR 2106: Error while computing sum in Initial
    at org.apache.pig.builtin.LongSum$Initial.exec(LongSum.java:87)
    at org.apache.pig.builtin.LongSum$Initial.exec(LongSum.java:65)
    at org.apache.pig.backend.hadoop.executionengine.physicalLayer.expressionOperators.POUserFunc.getNext(POUserFunc.java:216)
    at org.apache.pig.backend.hadoop.executionengine.physicalLayer.expressionOperators.POUserFunc.getNext(POUserFunc.java:253)
    at org.apache.pig.backend.hadoop.executionengine.physicalLayer.PhysicalOperator.getNext(PhysicalOperator.java:334)
    at org.apache.pig.backend.hadoop.executionengine.physicalLayer.relationalOperators.POForEach.processPlan(POForEach.java:332)
    at org.apache.pig.backend.hadoop.executionengine.physicalLayer.relationalOperators.POForEach.getNext(POForEach.java:284)
    at org.apache.pig.backend.hadoop.executionengine.physicalLayer.PhysicalOperator.processInput(PhysicalOperator.java:290)
    at org.apache.pig.backend.hadoop.executionengine.physicalLayer.relationalOperators.POLocalRearrange.getNext(POLocalRearrange.java:256)
    at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigGenericMapBase.runPipeline(PigGenericMapBase.java:267)
    at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigGenericMapBase.map(PigGenericMapBase.java:262)
    at org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigGenericMapBase.map(PigGenericMapBase.java:64)
    at org.apache.hadoop.mapreduce.Mapper.run(Mapper.java:144)
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:771)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:375)
    at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:212)
Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long
    at org.apache.pig.builtin.LongSum$Initial.exec(LongSum.java:79)
    ... 15 more

引起我注意的一行是:

Caused by: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long

这让我相信提取函数没有将字节字段转换为所需的数据类型(长)。

有没有办法强制提取函数转换为正确的数据类型?如何在无需对所有记录执行 FOREACH 的情况下转换值? (将时间转换为 unix 时间戳并尝试查找 MIN 时会发生同样的问题。我绝对想找到一个不需要不必要投影的解决方案。

任何指针将不胜感激。非常感谢您的帮助。

问候, 豪尔赫 C.

附:我在 Amazon 弹性 mapreduce 服务上以交互模式运行它。

【问题讨论】:

【参考方案1】:

您是否尝试过cast 从 UDF 检索到的数据?在此处应用架构不会执行任何转换。

例如

logs_base = 
   FOREACH raw_logs
   GENERATE
       FLATTEN(
           (tuple(LONG,LONG,CHARARRAY,....)) EXTRACT(line, '^...')
       )
       AS (account_id: INT, ...);

【讨论】:

感谢 Romain,效果很好。我的印象是应用模式会指导 pig 隐式转换。我想知道为什么在 aws.amazon.com/articles/2729 的教程中使用了聚合 SUM 函数,而没有对加载的数据进行显式强制转换...再次感谢。

以上是关于如何在 Apache Pig 上强制执行正确的数据类型?的主要内容,如果未能解决你的问题,请参考以下文章

执行远程 Apache Pig 脚本时如何查看终端日志

如何使用 Apache 在特定页面上正确强制使用 HTTPS

Apache Pig:在 Pig 中处理数据类型时面临问题

如何使用 apache pig 在 hadoop 集群上加载文件?

为啥 apache 强制执行 SSL (https)?如何撤消此操作?

Apache Pig 如何在加载功能中加入白名单或黑名单?