【问题标题】:Hive table creation using OpenCsv SerDe使用 OpenCsv SerDe 创建 Hive 表
【发布时间】:2018-04-04 18:26:27
【问题描述】:

我使用以下命令创建了表 -

 create table cust(event int, pid int, REQ_FROM_IP int, REQ_CITY_ID int, REQ_STATE_ID int, REQ_COUNTRY_ID int, key String) 
 ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'                                                                                 
 WITH SERDEPROPERTIES (                                                                                                                        
  "separatorChar" = "|",                                                                                                                       
    "quoteChar"     = "'",                                                                                                                     
    "escapeChar"    = "\\"                                                                                                                     
 )STORED AS TEXTFILE; 

但是创建的表的所有列都是字符串!

    desc cust;
    OK
event                   string                  from deserializer   
pid                     string                  from deserializer   
req_from_ip             string                  from deserializer   
req_city_id             string                  from deserializer   
req_state_id            string                  from deserializer   
req_country_id          string                  from deserializer   
key                     string                  from deserializer  

是 SerDe 弄乱了数据结构吗?

【问题讨论】:

    标签: hive opencsv


    【解决方案1】:

    通过阅读源代码,看起来 OpenCSVSerde 将始终输出字符串列,而不考虑 HiveQL 查询中实际指定的类型。

    一个潜在的(不是很漂亮的)解决方法可能是使用 OpenCSVSerde 来格式化临时表(定义可以与您当前对 cust 的定义相同,也许称它为 cust_staging。如果您使用如果您尝试以该格式加载数据并尝试在 Hive 中使用“正确”数据类型使用它,您可以像通常加载表一样填充 cust_staging,然后填充目标表 @ 987654324@ 带有 CTAS 语句,例如:

    CREATE TABLE cust AS SELECT
      CAST(event AS INT) AS event,
      CAST(pid AS INT) AS pid,
      CAST(REQ_FROM_IP AS INT) AS REQ_FROM_IP,
      CAST(REQ_CITY_ID AS INT) AS REQ_CITY_ID,
      CAST(REQ_STATE_ID AS INT) AS REQ_STATE_ID,
      CAST(REQ_COUNTRY_ID AS INT) AS REQ_COUNTRY_ID,
      key
    FROM cust_staging;
    

    现在cust 将拥有您期望的列类型:

    hive> DESCRIBE cust;
    OK
    event                       int                                 
    pid                         int                                 
    req_from_ip                 int                                 
    req_city_id                 int                                 
    req_state_id                int                                 
    req_country_id              int                                 
    key                         string                              
    Time taken: 0.546 seconds, Fetched: 7 row(s)
    

    根据@JeremyBeard 的出色意见,如果您可以从不使用“正确”类型实现数据,cust 实际上可以是一个视图:

    CREATE VIEW `cust` -- All the other stuff is the same
    

    要进一步深入研究这一推理,如果您的用例完全是只读的(您不必实际修改此数据),您可以将 cust_staging 定义为外部表(仍使用 OpenCSVSerde)指向您的管道分隔数据文件,然后将cust 定义为该外部表的视图。

    但是,如果您的用例是您需要以 OpenCSVSerde 格式存储包含非字符串列的表,那么您仍然可以创建 cust_staging 表(同样,使用您最初的定义)并填充数据反方向:

    INSERT INTO TABLE cust_staging SELECT * FROM cust;
    

    如果所有这些仍然感觉不够优雅(可以理解) - 解决方案可能是将 OpenCSVSerde 扩展为自定义 SerDe,它可以执行您希望它执行的操作,而无需中间临时表。

    【讨论】:

    • 对此的一种变体是将 CTAS 转换为视图,以便可以从原始文件中读取数据而无需进行预转换步骤。
    • @JeremyBeard +1 谢谢,很清楚 - 我已经在答案中添加了对此的讨论,以及在纯粹阅读用例的情况下实现外部表视图的另一个变体-仅。
    • @rchang,JeremyBeard 感谢您的帮助。但是,我只是对表示为字符串的数字进行了数值运算。 (做了req_state_id的总和。虽然不合逻辑,但只是为了测试)。我发现它运行得非常好,这表明 Hive 查询运行器是弱类型的。那么,当我可以对数字字符串进行相同的操作时,我是否需要使用实际类型?
    • 创建两个表意味着双重存储,这在 Hive 处理大数据的情况下尤其难以承受。我认为扩展 OpenCsv SerDe 对我来说会更好。
    • @CTRL-ALT-DELETE 从长远来看,SerDe 扩展方法可能是最干净的,所以我同意你的观点。关于仅将数据作为字符串摄取并让 Hive 运行时动态转换事物,这也是一种有效的方法,只要您对传入数据的质量有信心(在您期望整数的地方不会有非数字数据,例如)。
    猜你喜欢
    • 2021-10-04
    • 1970-01-01
    • 2013-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多