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

时间:2019-09-05 18:17:35

标签: python csv hive pyspark hive-serde

您好,亲爱的stackoverflow社区

这是我的问题:


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

B)我需要根据这些数据创建一个spark数据框, 希望转换t -> truef -> false。 为此,我创建了一个Hive数据库和一个临时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 ...”(终止于...的字段)

所有人都给我

  • 以空值代替“ t”和“ f”,或
  • 空df(df.head(5)中没有)或
  • 语法错误,或者
  • 大约100页的Java异常。

我要说的真正问题是,没有一个单独的带有LazySimpleSerDe的CREATE TABLE示例。 可以完成文档中所述的工作。

我真的非常感谢您的帮助或任何想法。我几乎拔了全部头发。

提前谢谢!

1 个答案:

答案 0 :(得分:0)

根据patches in jira issues

SET hive.lazysimple.extended_boolean_literal=true;

例如,如果您有一个制表符分隔的文本文件,其中包含标题行,而't'/'f'表示true false:

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