hive建表指定列分隔符为多字符分隔符实战(默认只支持单字符)_hive row formate ###-程序员宅基地

技术标签: hive  多字符列分隔符  列分割符  分隔符  

1、背景:

        后端日志采集完成,清洗入hive表的过程中,发现字段之间的单一字符的分割符号已经不能满足列分割需求,因为字段值本身可能包含分隔符。所以列分隔符使用多个字符列分隔符迫在眉睫。

hive在建表时,通常使用
ROW FORMAT DELIMITED
FIELDS TERMINATED BY "|#"  来限定数据中各个字段的分隔符,这种方式只支持单个分隔符,即:实际只会按照"|"进行分割,

默认情况下,Hive对于分隔符只支持单字符,不过Hive自带一个工具jar包,这个包支持正则和多字符方式定义分隔符。

hive从0.14版本以后支持MultiDelimitSerDe,可以比较优雅多解决多分隔符问题。

ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe' WITH SERDEPROPERTIES ("field.delim"="|#$")

2、官方对列支持多个字符的分隔符调研 

参考MultiDelimitSerDe - Apache Hive - Apache Software Foundation

Introduction:

Introduced in HIVE-5871, MultiDelimitSerDe allows user to specify multiple-character string as the field delimiter when creating a table.

Version:

Hive 0.14.0 and later.

Hive SQL Syntax:

You can use MultiDelimitSerDe in a create table statement like this:

CREATE TABLE test (
 id string,
 hivearray array<binary>,
 hivemap map<string,int>) 
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.MultiDelimitSerDe'                  
WITH SERDEPROPERTIES ("field.delim"="[,]","collection.delim"=":","mapkey.delim"="@");

where field.delim is the field delimiter, collection.delim and mapkey.delim is the delimiter for collection items and key value pairs, respectively. 

HIVE-20619 moved MultiDelimitSerDe to hive.serde2 in release 4.0.0, so user won't have to install hive-contrib JAR into the HiveServer2 auxiliary directory.

Limitations:

  • Among the delimiters, field.delim is mandatory and can be of multiple characters, while collection.delim and mapkey.delim is optional and only support single character.
  • Nested complex type is not supported, e.g. an Array<Array>.
  • To use MultiDelimitSerDe prior to Hive release 4.0.0, you have to add the hive-contrib jar to the class path, e.g. with the add jar command.

3、小试牛刀,报错

建表时直接使用 

ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe' WITH SERDEPROPERTIES ("field.delim"="|#$")

执行查询报错:Class org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe not found
根据网上的方案:进入hive执行(jar包路径根据自己环境路径对应修改)

 add jar /usr/hdp/3.1.5.0-152/hive/lib/hive-contrib.jar
 
CREATE EXTERNAL TABLE `table_tset`(
id string,
name string,
year string)                           
PARTITIONED BY (                                   
  `year` string)                                     
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe' WITH SERDEPROPERTIES ("field.delim"="|#$")
LOCATION 
  'hdfs://CMBHHA/apps/hive/datahouse/test/table_tset'
 

4、几经搜索,问题终于解决,附上完整示例

4.1、找到和hive版本对应的hive-contrib包,下载jar上传到hdfs上

org/apache/hive/hive-contrib所有版本Jar文件及下载 -时代Java

hive-contrib包下载链接

4.2、以三个等号作为列分隔符 构建hive表的完整demo

add jar hdfs://team/work/libs/xxx/hive-contrib-2.0.1.jar;

drop table if exists mb_tmp.yz_1013;
create table if not exists mb_tmp.yz_1013(
test_id int,
work_place string,
other string
)
partitioned by(dt string)
ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe' WITH SERDEPROPERTIES ("field.delim"="===")

load data local inpath '/data/home/xxxx/client/ct_data_1010.txt' overwrite into table mb_tmp.yz_1013 partition(dt='2022-10-10');

其中 以三个等号分割进行作为列分割的数据如下:

[work@xxxx client]$ cat ct_data_1010.txt
10011===beijing===chu==shi
10012===tianjin===chang==chun
10013===zhengzhou===si==ji
100014===zhangda===j==ob

4.3、结果验证

hive> desc  mb_tmp.yz_1013;
OK
test_id             	int                 	from deserializer   
work_place          	string              	from deserializer   
other               	string              	from deserializer   
dt                  	string              	                    
	 	 
# Partition Information	 	 
# col_name            	data_type           	comment             
	 	 
dt                  	string              	                    
Time taken: 0.332 seconds, Fetched: 9 row(s)

hive> set hive.cli.print.header=true;

hive> select * from mb_tmp.yz_1013 limit 100;
OK
yz_1013.test_id	yz_1013.work_place	yz_1013.other	yz_1013.dt
10011	beijing	chu==shi	2022-10-10
10012	tianjin	chang==chun	2022-10-10
10013	zhengzhou	si==ji	2022-10-10
100014	zhangda	j==ob	2022-10-10
Time taken: 0.51 seconds, Fetched: 4 row(s)
hive> select other,'****',dt,work_place,test_id from mb_tmp.yz_1013 limit 100;
OK
other	c1	dt	work_place	test_id
chu==shi	****	2022-10-10	beijing	10011
chang==chun	****	2022-10-10	tianjin	10012
si==ji	****	2022-10-10	zhengzhou	10013
j==ob	****	2022-10-10	zhangda	100014
Time taken: 0.356 seconds, Fetched: 4 row(s)

5、参考:

1)、Hive多字符分隔符支持https://baijiahao.baidu.com/s?id=1617938645018071295&wfr=spider&for=pc

2、Hive在0.14及以后版本支持字段的多分隔符,官方文档https://cwiki.apache.org/confluence/display/Hive/MultiDelimitSerDe

3、Hive中的自定义分隔符(包含Hadoop和Hive详细安装)

 https://blog.csdn.net/github_39577257/article/details/89020980

6、Hive 自带的多字符分割使用demo2

默认情况下,Hive对于分隔符只支持单字符,不过Hive自带一个工具jar包,这个包支持正则和多字符方式定义分隔符。

1). 查询hive自带的工具jar包位置
find / -name hive-contrib-*.jar
2). 将上面搜索到的jar包配置到配置hive-site.xml文件中
<property>
  <name>hive.aux.jars.path</name>
  <value>file:///opt/apache-hive-1.2.2-bin/lib/hive-contrib-1.2.2.jar</value>
  <description>Added by tiger.zeng on 20120202.These JAR file are available to all users for all jobs</description>
</property>

上面配置之后可以不用重启Hive服务,只需要重新进入Hive CLI就可生效,且是永久的。也可以配置为临时的,就是在进入Hive CLI后,临时加载这个jar包,执行如下:
hive> add jar file:///opt/apache-hive-1.2.2-bin/lib/hive-contrib-1.2.2.jar
3). 使用
准备如下数据,分隔符为 |#|,

3324|#|003|#|20190816 09:16:18|#|0.00|#|2017-11-13 12:00:00
3330|#|009|#|20190817 15:21:03|#|1234.56|#|2017-11-14 12:01:00

建表时如下声明与定义如下,并加载数据,查询数据:

drop table if exists split_test;
CREATE  TABLE  split_test(
id   INT COMMENT '借阅查询ID',
number   STRING COMMENT '流水号',
`date`   STRING COMMENT '查询返回日期',
loanamount   DOUBLE COMMENT '借款金额范围',
createtime   TIMESTAMP COMMENT '创建时间'
)ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe'
WITH SERDEPROPERTIES ("field.delim"="|#|")
STORED AS TEXTFILE;


 --加载数据
LOAD DATA LOCAL INPATH '/root/split_test.txt'  OVERWRITE INTO TABLE split_test;
 
查询结果如下:
--查询数据
hive> select * from split_test;
OK
3324    003     20190816 09:16:18       0.0     2017-11-13 12:00:00
3330    009     20190817 15:21:03       1234.56 2017-11-14 12:01:00
Time taken: 0.11 seconds, Fetched: 2 row(s)
 

7、Hive 自定义分隔符例子


自定义部分使用 Java 编写,使用Idea新建一个 Maven项目。
https://blog.csdn.net/github_39577257/article/details/89020980

8、hive特殊分隔符,不可见的分隔符 枚举

1.hive默认字段分隔符^A(使用vim文本编辑显示),常用ASCII八进制 '\001' 或者UNICODE编码十六进制 '\u0001' 进行设置;通过notepad++打开显示为SOH

2.hive特殊分隔符^B(使用vim文本编辑显示),常用ASCII八进制 '\002' 或者UNICODE编码十六进制 '\u0002' 进行设置;通过notepad++打开显示为STX

3.hive特殊分隔符^C(使用vim文本编辑显示),常用ASCII八进制 '\003' 或者UNICODE编码十六进制 '\u0003' 进行设置;通过notepad++打开显示为ETX·

此外,不同编程语音使用hive中\u0001、\0001、\0010、\u0010等分隔符切割需要不同写法

以‘\u0010’为例
hive sql使用split函数时,如果字段内使用的是特殊分隔符()需要用split(xxx,‘\u0010’)才能正常切割。
如果是使用java写mr代码,那么需要使用的是"\0010"

​ 9、hive分隔符_HIVE-默认分隔符的(linux系统的特殊字符)查看,输入和修改

hive表分隔符修改实操(兼容sqoop)_hive修改分隔符-程序员宅基地

#修改分隔符为逗号 ,

ALTER TABLE table_name SET SERDEPROPERTIES ('field.delim' = ',' , 'serialization.format'=',');

#修改分隔符为\001,在linux的vim中显示为^A,是hive默认的分隔符

ALTER TABLE table_name SET SERDEPROPERTIES ('field.delim' = '\001' , 'serialization.format'='\001');

#修改分隔符为制表符\t

ALTER TABLE table_name SET SERDEPROPERTIES ('field.delim' = '\t' , 'serialization.format'='\t');


重点知识:
field.delim 指定表的两个列字段之间的文件中的字段分隔符.
serialization.format 指定数据文件序列化时表中两个列字段之间的文件中的字段分隔符.
对于分区表,每个分区可以有不同的分隔符属性
alter语法修改分区表的分隔符后,不会影响已有分区数据读写,只会对后续新写入的数据生效。这一点非常友好
alter语法修改分隔符只针对于后续新增数据有效,拿分区表而言,比如现在有2个分区,day=2020-05-01,day=2020-05-02,分隔符是\t, 通过alter把分隔符改为\001,再写入写的分区day=2020-05-03

可以通过desc formatted tablename partition(key=value)语法查看每个分区的分隔符,那么2020-05-01,2020-05-02的分区依然是\t分隔符,2020-05-03分区的分隔符是\001;而且可以通过hive正常读写操作这三个分区而不会出现任何问题

通过desc formatted table查看该表的分隔符,发现已经变为\001

10、hive列分隔符和行分隔符概述

一)、Hive中默认的分割符如下

分隔符 描述
\n 对于文本文件来说,每行都是一条记录,因此换行符可以分隔记录
^A(Ctrl+A) 用于分隔字段(列)。在CREATE TABLE语句中可以使用八进制编码\001表示
^B 用于分隔ARRAY或者STRUCT中的元素,或用于MAP中键-值对之间的分隔。在CREATE TABLE语句中可以使用八进制编码\002表示
^C 用于MAP中键和值之间的分隔。在CREATE TABLE语句中可以使用八进制编码\003表示


 二)、分隔符的指定与使用
hive中在创建表时,一般会根据导入的数据格式来指定字段分隔符和列分隔符。一般导入的文本数据字段分隔符多为逗号分隔符或者制表符(但是实际开发中一般不用着这种容易在文本内容中出现的的符号作为分隔符),当然也有一些别的分隔符,也可以自定义分隔符。有时候也会使用hive默认的分隔符来存储数据。
 

hive (fdm_sor)> create table fdm_sor.mytest_tmp2(
              >  id int comment'编号',
              >  name string comment '名字'
              >  );
 
hive (fdm_sor)> show create table mytest_tmp2;
CREATE  TABLE `mytest_tmp2`(
  `id` int COMMENT '编号', 
  `name` string COMMENT '名字')
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' --hive默认的分割方式,即行为\n,列为^A
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat'    --hive默认的存储格式为textfile
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION                                    --内部表的默认的存储路径
  'hdfs://hadoop102:9000/user/hive/warehouse/fdm_sor.db/mytest_tmp2'
TBLPROPERTIES (
  'transient_lastDdlTime'='1526176805')
 
 
hive (fdm_sor)> create table  fdm_sor.mytest_tmp3(
              >   id int comment'编号',
              >  name string comment '名字'
              >  )
              >  row format delimited 
              >  fields terminated by '\001'  --这里可以指定别的分隔符,如‘\t’,'$'等分隔符
              >  COLLECTION ITEMS TERMINATED BY '\002'  -- 集合间的分隔符
              >  MAP KEYS TERMINATED BY '\003'          -- Map键与值之间的分隔符
              >  LINES TERMINATED BY '\n'               -- 行分隔符  
              >  stored as textfile;                    -- 存储格式为textfile
 
 
hive (fdm_sor)> show create table fdm_sor.mytest_tmp3;
OK
createtab_stmt
CREATE  TABLE `fdm_sor.mytest_tmp3`(
  `id` int COMMENT '编号', 
  `name` string COMMENT '编号')
ROW FORMAT DELIMITED 
  FIELDS TERMINATED BY '\u0001' 
  LINES TERMINATED BY '\n' 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  'hdfs://hadoop102:9000/user/hive/warehouse/fdm_sor.db/mytest_tmp3'
TBLPROPERTIES (
  'transient_lastDdlTime'='1526176859')

-注意:ROW FORMAT DELIMITED这组关键字必须要写在其他子句(除了STORED AS…)子句之前。

 如上可以看出hive默认的列分割类型为org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe,

而这其实就是^A分隔符,hive中默认使用^A(ctrl+A)作为列分割符,如果用户需要指定的话,等同于row format delimited fields terminated by '\001',因为^A八进制编码体现为'\001'.所以如果使用默认的分隔符,可以什么都不加,也可以按照上面的指定加‘\001’为列分隔符,效果一样。

       hive默认使用的行分隔符是'\n'分隔符 ,也可以加一句:LINES TERMINATED BY '\n' ,加不加效果一样。但是区别是hive可以通过row format delimited fields terminated by '\t'这个语句来指定不同的分隔符,但是hive不能够通过LINES TERMINATED BY '$$'来指定行分隔符,目前为止,hive的默认行分隔符仅支持‘\n’字符。否则报错。

hive (fdm_sor)>  create table  fdm_sor.mytest_tm4(
              >   id int comment'编号',
              >  name string comment '名字'
              >  )
              >  lines terminated by '\t';
FAILED: ParseException line 5:1 missing EOF at 'lines' near ')'

         一般来说hive的默认行分隔符都是换行符,如果非要自定义行分隔符的话,可以通过自定义Inputformat和outputformat类来指定特定行分隔符和列分隔符,一般公司实际开发中也都是这么干的,具体使用。

       当然如hive中集合数据类型struct ,map,array,也都有默认的字段分隔符,也都可以指定字段分隔符。hive中对于上述三个集合数据类型的默认字段分隔符是^B,八进制体现为‘\002’,用collection items terminated by '\002'语句来指定分隔符,对于map来说,还有键值之间的分割符,可以用map keys terminated by  '\003'(^C)来指定分隔符。

三)、建好表之后更改字段分隔符

   参见第九步

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/helloxiaozhe/article/details/133748653

智能推荐

JWT(Json Web Token)实现无状态登录_无状态token登录-程序员宅基地

文章浏览阅读685次。1.1.什么是有状态?有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。缺点是什么?服务端保存大量数据,增加服务端压力 服务端保存用户状态,无法进行水平扩展 客户端请求依赖服务.._无状态token登录

SDUT OJ逆置正整数-程序员宅基地

文章浏览阅读293次。SDUT OnlineJudge#include<iostream>using namespace std;int main(){int a,b,c,d;cin>>a;b=a%10;c=a/10%10;d=a/100%10;int key[3];key[0]=b;key[1]=c;key[2]=d;for(int i = 0;i<3;i++){ if(key[i]!=0) { cout<<key[i.

年终奖盲区_年终奖盲区表-程序员宅基地

文章浏览阅读2.2k次。年终奖采用的平均每月的收入来评定缴税级数的,速算扣除数也按照月份计算出来,但是最终减去的也是一个月的速算扣除数。为什么这么做呢,这样的收的税更多啊,年终也是一个月的收入,凭什么减去12*速算扣除数了?这个霸道(不要脸)的说法,我们只能合理避免的这些跨级的区域了,那具体是那些区域呢?可以参考下面的表格:年终奖一列标红的一对便是盲区的上下线,发放年终奖的数额一定一定要避免这个区域,不然公司多花了钱..._年终奖盲区表

matlab 提取struct结构体中某个字段所有变量的值_matlab读取struct类型数据中的值-程序员宅基地

文章浏览阅读7.5k次,点赞5次,收藏19次。matlab结构体struct字段变量值提取_matlab读取struct类型数据中的值

Android fragment的用法_android reader fragment-程序员宅基地

文章浏览阅读4.8k次。1,什么情况下使用fragment通常用来作为一个activity的用户界面的一部分例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输_android reader fragment

FFT of waveIn audio signals-程序员宅基地

文章浏览阅读2.8k次。FFT of waveIn audio signalsBy Aqiruse An article on using the Fast Fourier Transform on audio signals. IntroductionThe Fast Fourier Transform (FFT) allows users to view the spectrum content of _fft of wavein audio signals

随便推点

Awesome Mac:收集的非常全面好用的Mac应用程序、软件以及工具_awesomemac-程序员宅基地

文章浏览阅读5.9k次。https://jaywcjlove.github.io/awesome-mac/ 这个仓库主要是收集非常好用的Mac应用程序、软件以及工具,主要面向开发者和设计师。有这个想法是因为我最近发了一篇较为火爆的涨粉儿微信公众号文章《工具武装的前端开发工程师》,于是建了这么一个仓库,持续更新作为补充,搜集更多好用的软件工具。请Star、Pull Request或者使劲搓它 issu_awesomemac

java前端技术---jquery基础详解_简介java中jquery技术-程序员宅基地

文章浏览阅读616次。一.jquery简介 jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互 jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax_简介java中jquery技术

Ant Design Table换滚动条的样式_ant design ::-webkit-scrollbar-corner-程序员宅基地

文章浏览阅读1.6w次,点赞5次,收藏19次。我修改的是表格的固定列滚动而产生的滚动条引用Table的组件的css文件中加入下面的样式:.ant-table-body{ &amp;amp;::-webkit-scrollbar { height: 5px; } &amp;amp;::-webkit-scrollbar-thumb { border-radius: 5px; -webkit-box..._ant design ::-webkit-scrollbar-corner

javaWeb毕设分享 健身俱乐部会员管理系统【源码+论文】-程序员宅基地

文章浏览阅读269次。基于JSP的健身俱乐部会员管理系统项目分享:见文末!

论文开题报告怎么写?_开题报告研究难点-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏15次。同学们,是不是又到了一年一度写开题报告的时候呀?是不是还在为不知道论文的开题报告怎么写而苦恼?Take it easy!我带着倾尽我所有开题报告写作经验总结出来的最强保姆级开题报告解说来啦,一定让你脱胎换骨,顺利拿下开题报告这个高塔,你确定还不赶快点赞收藏学起来吗?_开题报告研究难点

原生JS 与 VUE获取父级、子级、兄弟节点的方法 及一些DOM对象的获取_获取子节点的路径 vue-程序员宅基地

文章浏览阅读6k次,点赞4次,收藏17次。原生先获取对象var a = document.getElementById("dom");vue先添加ref <div class="" ref="divBox">获取对象let a = this.$refs.divBox获取父、子、兄弟节点方法var b = a.childNodes; 获取a的全部子节点 var c = a.parentNode; 获取a的父节点var d = a.nextSbiling; 获取a的下一个兄弟节点 var e = a.previ_获取子节点的路径 vue

推荐文章

热门文章

相关标签