LanguageManual Transform

Transform/Map-Reduce Syntax

用户还可以使用 Hive 语言本身支持的功能,在数据流中插入自己的自定义 Map 器和精简器。例如为了运行自定义的 Map 器脚本 map_script 和自定义的 reducer 脚本 reduce_script,用户可以发出以下命令,该命令使用 TRANSFORM 子句嵌入 Map 器和化简器脚本。

默认情况下,列将被转换为* STRING 并由 TAB 分隔,然后再馈送到用户脚本;同样,所有 NULL 值都将转换为 Literals 字符串 N ,以便将 NULL 值与空字符串区分开。用户脚本的标准输出将被视为 TAB 分隔的 STRING 列,任何仅包含 N 的单元格将被重新解释为 NULL,然后将得到的 STRING 列强制转换为数据以通常的方式在表声明中指定类型。用户脚本可以将调试信息输出为标准错误,这将显示在 hadoop 的任务详细信息页面上。这些默认值可以用 ROW FORMAT ... *覆盖。

在 Windows 中,使用“ cmd/c your_script”而不是“ your_script”

Warning

您有责任在转换之前对任何 STRING 列进行消毒。如果您的“ STRING”列中包含标签,则身份转换器不会将您的开始信息还给您!为此,请参见REGEXP_REPLACE并将选项卡替换为 TRANSFORM()调用中的其他字符。

Warning

形式上,* MAP ... REDUCE ... SELECT TRANSFORM(...)*的语法转换。换句话说,它们充当查询 Reader 的 Comments 或 Comments。注意:使用这些关键字可能是“危险的”,因为(例如)键入“ REDUCE”不会强制执行还原阶段,而键入“ MAP”不会强制执行新的 Map 阶段!

另请参见排序方式/群集方式/分布方式和 Larry Ogrodnek 的blog post

clusterBy: CLUSTER BY colName (',' colName)*
distributeBy: DISTRIBUTE BY colName (',' colName)*
sortBy: SORT BY colName (ASC | DESC)? (',' colName (ASC | DESC)?)*

rowFormat
  : ROW FORMAT
    (DELIMITED [FIELDS TERMINATED BY char] 
               [COLLECTION ITEMS TERMINATED BY char]
               [MAP KEYS TERMINATED BY char]
               [ESCAPED BY char]
               [LINES SEPARATED BY char]
     | 
     SERDE serde_name [WITH SERDEPROPERTIES 
                            property_name=property_value, 
                            property_name=property_value, ...])

outRowFormat : rowFormat
inRowFormat : rowFormat
outRecordReader : RECORDREADER className

query:
  FROM (
    FROM src
    MAP expression (',' expression)*
    (inRowFormat)?
    USING 'my_map_script'
    ( AS colName (',' colName)* )?
    (outRowFormat)? (outRecordReader)?
    ( clusterBy? | distributeBy? sortBy? ) src_alias
  )
  REDUCE expression (',' expression)*
    (inRowFormat)?
    USING 'my_reduce_script'
    ( AS colName (',' colName)* )?
    (outRowFormat)? (outRecordReader)?

  FROM (
    FROM src
    SELECT TRANSFORM '(' expression (',' expression)* ')'
    (inRowFormat)?
    USING 'my_map_script'
    ( AS colName (',' colName)* )?
    (outRowFormat)? (outRecordReader)?
    ( clusterBy? | distributeBy? sortBy? ) src_alias
  )
  SELECT TRANSFORM '(' expression (',' expression)* ')'
    (inRowFormat)? 
    USING 'my_reduce_script'
    ( AS colName (',' colName)* )?
    (outRowFormat)? (outRecordReader)?

基于 SQL 标准的授权不允许进行 TRANSFORM

在 Hive 0.13.0 和更高版本(HIVE-6415)中配置基于 SQL 标准的授权时,不允许 TRANSFORM 子句。

TRANSFORM Examples

Example #1:

FROM (
    FROM pv_users
    MAP pv_users.userid, pv_users.date
    USING 'map_script'
    AS dt, uid
    CLUSTER BY dt) map_output
  INSERT OVERWRITE TABLE pv_users_reduced
    REDUCE map_output.dt, map_output.uid
    USING 'reduce_script'
    AS date, count;
  FROM (
    FROM pv_users
    SELECT TRANSFORM(pv_users.userid, pv_users.date)
    USING 'map_script'
    AS dt, uid
    CLUSTER BY dt) map_output
  INSERT OVERWRITE TABLE pv_users_reduced
    SELECT TRANSFORM(map_output.dt, map_output.uid)
    USING 'reduce_script'
    AS date, count;

Example #2

FROM (
    FROM src
    SELECT TRANSFORM(src.key, src.value) ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.TypedBytesSerDe'
    USING '/bin/cat'
    AS (tkey, tvalue) ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.TypedBytesSerDe'
    RECORDREADER 'org.apache.hadoop.hive.contrib.util.typedbytes.TypedBytesRecordReader'
  ) tmap
  INSERT OVERWRITE TABLE dest1 SELECT tkey, tvalue

无架构的 Map-Reduce 脚本

如果* USING my_script 之后没有 AS 子句,则 Hive 假定脚本的输出包含两部分:key 在第一个选项卡之前,而 value 则在第一个选项卡之后。请注意,这与指定 AS 键,值*不同,因为在这种情况下,如果存在多个标签,则值将仅包含第一个标签和第二个标签之间的部分。

注意,我们可以直接执行* CLUSTER BY 键*,而无需指定脚本的输出模式。

FROM (
    FROM pv_users
    MAP pv_users.userid, pv_users.date
    USING 'map_script'
    CLUSTER BY key) map_output
  INSERT OVERWRITE TABLE pv_users_reduced
    REDUCE map_output.key, map_output.value
    USING 'reduce_script'
    AS date, count;

键入 TRANSFORM 的输出

脚本的输出字段默认情况下被键入为字符串;例如在

SELECT TRANSFORM(stuff)
  USING 'script'
  AS thing1, thing2

可以使用以下语法立即将其强制转换:

SELECT TRANSFORM(stuff)
  USING 'script'
  AS (thing1 INT, thing2 INT)