PySpark/Hive:如何使用 LazySimpleSerDe 创建表以转换布尔值“t”/“f”?

Posted

技术标签:

【中文标题】PySpark/Hive:如何使用 LazySimpleSerDe 创建表以转换布尔值“t”/“f”?【英文标题】:PySpark/Hive: how to CREATE TABLE with LazySimpleSerDe to convert boolean 't' / 'f'? 【发布时间】:2019-09-05 18:17:35 【问题描述】:

亲爱的***社区,你好,

这是我的问题:


A) 我在 csv 中有一些布尔列的数据; 不幸的是,这些列中的值是tf(单字母); 这是我无法控制的神器(来自 Redshift)。

B) 我需要从这些数据中创建一个 spark 数据框, 希望转换t -> truef -> false。 为此,我创建了一个 Hive DB 和一个临时 Hive 表 然后 SELECT * 来自它,像这样:

sql_str = """SELECT * FROM db.s_t """.format(
             db=hive_db_name, s=schema, t=table)
df = sql_cxt.sql(sql_str)

这行得通,我可以打印 df,它为我的所有列提供了正确的数据类型。 但是:

C) 如果我这样创建表:

CREATE EXTERNAL TABLE IF NOT EXISTS db.schema_table(cols)                    
ROW FORMAT DELIMITED                                                                                          
FIELDS TERMINATED BY '|t'                                                                                     
STORED AS TEXTFILE 
LOCATION ...

,这会将我所有的 tf 转换为 Null。

所以:

D) 我发现LazySimpleSerDe 大概必须按照我的意思去做(即时将tf 转换为truefalse)。来自https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties(引用):

"""
hive.lazysimple.extended_boolean_literal
Default Value: false
Added in: Hive 0.14 with HIVE-3635
LazySimpleSerDe uses this property to determine 
if it treats 'T', 't', 'F', 'f', '1', and '0' as extended, 
legal boolean literals, in addition to 'TRUE' and 'FALSE'. 
The default is false, which means only 'TRUE' and 'FALSE' 
are treated as legal boolean literals.
"""

据此(或至少我认为如此),我现在在 Hive DB 中创建一个表,如下所示:

create_table_sql = """
    CREATE EXTERNAL TABLE IF NOT EXISTS db_name.schema_table(cols)
    ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
    WITH SERDEPROPERTIES ("separatorChar" = "\|")
    STORED AS TEXTFILE
    LOCATION 'loc'
    TBLPROPERTIES ('hive.lazysimple.extended_boolean_literal'='true')
    """.format(db_name=hive_db_name,
               schema=schema,
               table=table,
               cols=",\n".join(cols),
               loc=location)

return sql_cxt.sql(create_table_sql)

这确实创建了一个表, 我可以再次看到所有具有正确数据类型的列, df.count() 是正确的,但 df.head(3) 仍然 为我的布尔列提供所有值 == Null。

(:___


我为我的 CREATE TABLE 尝试了几个小时的不同变体...

带或不带 SERDEPROPERTIES, 有或没有 TBLPROPERTIES, 带有或不带有“FIELDS TERMINATED BY...”,

等等

都给我一个

用 Null 代替 't' 和 'f',或者 一个空的df(df.head(5)没有),或者 语法错误,或 大约 100 页 Java 异常。

我想说,真正的问题是,没有一个使用 LazySimpleSerDe 的 CREATE TABLE 示例 完成文档中描述的工作。

我非常非常感谢您的帮助或任何想法。我拔掉了几乎所有的头发。

提前谢谢你!

【问题讨论】:

【参考方案1】:

根据patches in jira issues:

SET hive.lazysimple.extended_boolean_literal=true;

例如,如果你有一个制表符分隔的文本文件,包含标题行,'t'/'f' 表示真假:

create table mytable(myfield boolean)
row format delimited
fields terminated by '\t'
lines terminated by '\n'
location '/path'
tblproperties (
    'skip.header.line.count' = '1'
);
...
select count(*) from mytable where myfield is null; <-- returns 100% null
...
SET hive.lazysimple.extended_boolean_literal=true;
select count(*) from mytable where myfield is null; <-- changes the serde to interpret the booleans with a more forgiving interpretation, yields a different count

【讨论】:

以上是关于PySpark/Hive:如何使用 LazySimpleSerDe 创建表以转换布尔值“t”/“f”?的主要内容,如果未能解决你的问题,请参考以下文章

Pyspark/Hive 中带条件的加权运行总计

在 Pyspark/Hive 中有条件的运行总计

如何在 pyspark Hive SQL 中获取等效的 postgres 命令“nth_value”?

在 Pyspark/Hive 中处理不断变化的数据类型

如何在pyspark Hive SQL中获取等效的postgres命令'nth_value'以进行分区?

PySpark Hive 查询未显示输出