Hive 使用OpenCsv SerDe创建配置单元表

Hive 使用OpenCsv SerDe创建配置单元表,hive,opencsv,Hive,Opencsv,我使用以下命令创建了表- 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'

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

 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  

这是数据结构混乱的原因吗?

仔细阅读源代码,OpenCSVSerde似乎总是输出字符串列,而不考虑HiveQL查询中实际指定的类型

一个潜在的(不是很好的)解决方法是使用OpenCSVSerde格式化一个暂存表(定义可以与您当前对
cust
的定义相同,可以称之为
cust\u staging
)“正确”的数据类型,您可以像通常加载表一样填充
cust_staging
,然后用CTAS语句填充目标表
cust
,如:

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,它可以执行您希望它执行的操作,而不需要中间暂存表。

一种变体是将该CTA转换为视图,这样就可以从原始文件中读取数据,而无需预转换步骤。@JeremyBeard+1谢谢,非常准确-我已经添加了在回答中对此进行了讨论,还有另一种变体,在用例为纯只读的情况下将视图实现到外部表中。@rchang,JeremyBeard谢谢您的帮助。不过我只是对表示为字符串的数字进行了数字运算。(对req_state_id进行了求和。虽然不符合逻辑,但只是为了测试)。我发现它运行得非常好,这证明了Hive query runner是弱类型的。那么,当我可以对数字字符串执行相同的操作时,我是否需要使用实际类型?创建两个表意味着双重存储,这在Hive处理大数据时是无法承受的。我认为扩展OpenCsv会更好erDe@CTRL-ALT-DELETE从长远来看,SerDe扩展方法可能是最干净的,所以我同意你的观点。关于将数据作为字符串接收并让配置单元运行时动态转换内容,只要你对传入数据的质量有信心,这也是一种有效的方法(例如,在需要整数的地方不会有非数字数据)。