如何让hadoop接受带有复合where子句的sas传递查询?

rseugnpd  于 2021-05-29  发布在  Hadoop
关注(0)|答案(1)|浏览(564)

我试图通过在内部(hadoop端)where子句中发送附加条件来缩小传递查询(即,使用proc sql,而不是libname)到hadoop的sas数据集的范围。
例如,工作的代码如下所示(前面定义了dtpart宏变量,以便在hdfs中向下选择单个分区):

proc sql;
   connect to hadoop (server="&srvid" port=10000 user="&uid" pw="&passwd" schema=default );
   create table work.creative_lkup as
   select 
      advertiser_id,
      creative_id,
      creative,
      rendering_id,
      creative_type, 
      input("&dtpart.", yymmdd10.) as last_updt_dt format=mmddyy10.
   from connection to hadoop (
      select
       `advertiser id` as advertiser_id,
       `creative id` as creative_id,
       creative,
       `rendering id` as rendering_id,
       `creative type` as creative_type
      from default.match_table_creatives 
      where date_partition = "&dtpart." 
   ) 
   WHERE advertiser_id = '12345';
disconnect from hadoop;
quit;

注意:正如您所看到的,hadoop中的字段名不是sas标准的(因此在包含空格的名称周围有反记号),对于某些表,字段名和表名非常长。这使得在hadoop连接中简单地使用libname语句是不切实际的,因此我必须在procsql中使用connect-to来使用pass-through查询。
我想做的是将pass through中的“where advertiser_id='12345'”部分移到hadoop中。像这样:

proc sql;
   connect to hadoop (server="&srvid" port=10000 user="&uid" pw="&passwd" schema=default );
   create table work.creative_lkup as
   select 
      advertiser_id,
      creative_id,
      creative,
      rendering_id,
      creative_type, 
      input("&dtpart.", yymmdd10.) as last_updt_dt format=mmddyy10.
   from connection to hadoop (
      select
       `advertiser id` as advertiser_id,
       `creative id` as creative_id,
       creative,
       `rendering id` as rendering_id,
       `creative type` as creative_type
      from default.match_table_creatives 
      where date_partition = "&dtpart." 
         and `advertiser id` = '12345'
   );
disconnect from hadoop;
quit;

不幸的是,当我这样做的时候,我从hadoop中得到了一个很好的模糊错误,并传回sas:

ERROR: Prepare error: Error while processing statement: FAILED: Execution Error, return code 1 from 
   org.apache.hadoop.hive.ql.exec.mr.MapRedTask

我的问题是:是否有任何设置、选项或其他项目可以包含在procsql语句中,以便正确地使用where子句

似乎只有在where子句中有and时才会出现问题。我读过一些关于spde的内容(accelwhere=选项听起来很有前途),但是我不知道如何在procsql中使用这些选项,而且我在网上找到的参考资料似乎只指向libname语句中使用。
谢谢您。

dddzy1tm

dddzy1tm1#

问题似乎是在连接字符串(保存在sas宏变量uid中)中指定的用户实际上不存在于hadoop中。
宏变量uid包含一个通用用户id的名称(dev和prod环境的名称不同,因此需要一个宏变量)。假设用户存在于hadoop中,因为我能够使用这个userid从sas连接到hadoop,并通过简单的查询检索记录。
显然,情况并非如此。
如果hadoop环境中没有用户,hdfs中就没有主文件夹。我们的hadoop设置仍将处理“简单”查询(即,字段上没有转换;仅当条件可以针对分区字段时;没有连接;因为不需要构建mapreducer任务就可以从hdfs中的底层平面文件获取数据。只有在存在其他where条件(即分区字段除外)时,才需要创建mapreducer任务。在运行查询的用户的主文件夹中创建任务以及任务所需的任何临时文件。由于该用户的主文件夹不存在,mapreducer对象会抛出一个错误(尽管没有在配置单元中生成日志文件,因为没有地方生成日志文件,甚至没有创建此类文件的任务)。
它甚至允许在没有有效用户标识的情况下选择数据,这很愚蠢,但这是我们当前的设置。
因此,为了测试这个理论,我运行了以下代码(注意:我使用了用户名而不是宏变量)。

proc sql;
connect to hadoop (server="&srvid" port=10000 user="myuserid" pw="unnecessary" schema=default);
  create table work.creative_lkup2 as
  select 
     advertiser_id,
     creative_id,
     creative,
     rendering_id,
     creative_type, 
     input("&dtpart.", yymmdd10.) as last_updt_dt format=mmddyy10.
  from connection to hadoop (
select
      c.`advertiser id` as advertiser_id,
      c.`creative id` as creative_id,
      c.creative,
      c.`rendering id` as rendering_id,
      c.`creative type` as creative_type
from default.match_table_creatives c
where c.date_partition = "&dtpart." and c.`advertiser id` = "12345" 
   );
disconnect from hadoop;
quit;

这返回了大约80k条记录(10秒的cpu时间,但由于aws的io,它花费了将近10分钟)。
为了感谢所有看到这个问题并作出回应的人,我想提供一个从中吸取的教训,可能对你们有所帮助:
由于hadoop中的字段都定义为string,sas必须假设字段是可能的最长字符长度:32767。因此,数据量(大部分是空白)过多,导致传输速率缓慢。
我们提出的解决方案涉及使用execute(…)作为hadoop语句来创建和填充一个临时表,该临时表在将varchar字段摄取到sas之前已经正确地调整了varchar字段的大小(已经向下选择了所需的数据)。

proc sql;
   connect to hadoop (server="&srvid" port=10000 user="myuserid" pw="doesnt_matter" schema=default);
   execute (
      create table if not exists default.test_lkup_cre (
               advertiser_id Varchar(10),
               creative_id Varchar(10),
               creative Varchar(200),
               rendering_id Varchar(10),
               creative_type Varchar(16)
   )
) by hadoop;
   execute (
      insert into table default.test_lkup_cre
         select
               c.`advertiser id` as advertiser_id,
               c.`creative id` as creative_id,
               c.creative,
               c.`rendering id` as rendering_id,
               c.`creative type` as creative_type
         from default.match_table_creatives c
         where c.date_partition = "&dtpart." and c.`advertiser id` = "12345"
) by hadoop;
   create table work.creative_lkup3 as
   select 
     advertiser_id,
     creative_id,
     creative,
     rendering_id,
     creative_type, 
     input("&dtpart.", yymmdd10.) as last_updt_dt format=mmddyy10.
   from connection to hadoop (
      select
        advertiser_id,
        creative_id,
        creative,
        rendering_id,
        creative_type
      from default.test_lkup_cre
   );
   disconnect from hadoop;
quit;

它在46秒内返回了相同的~80k条记录。
希望这也能帮助其他人。

相关问题