文章目录
Hive的SerDe
1 hql读取/动态加载数据的解析
--建表语句:
create table t2(
id int,
name string
)
row format delimited
fields terminated by '\t';
--第一个类型:
实际上delimited 对应一个类型:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
fields terminated by 后指定的分隔符,是要传入LazySimpleSerDe类型中的切分方法的形参的。
--底层的第二个类型:
INPUTFORMAT 对应的具体的输入规则的类型,默认是:org.apache.hadoop.mapred.TextInputFormat
此类型主要决定记录阅读区如何解析一行记录,通常使用换行符作为记录分隔符。
--底层的第三个类型:org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
OUTPUTFORMAT 指向的具体的输出格式的类型,决定了在动态加载数据时,如何存储数据到文字中,通常会忽略Key3.
--select 过程:
是数据文件“反序列化”到内存中的一个过程。 数据文件中的一条记录----->row对象
--insert 过程:
是内存中的数据“序列化”到磁盘文件中的过程。 row对象-------->数据文件里的记录
2 常用的SerDe类型
-- 默认SerDe
-- CSVSerDe
-- JSONSerDe
-- RegexSerDe
-- TSVSerde
row format delimited fields terminated by '符号' -- 指定列分隔符
line terminated by '\n' -- 指定行分隔符
2.1 LazySimpleSerde
-- LazySimpleSerde是hive表默认使用的SerDe类型
-- 对应的默认行分隔符是\n
-- 对应的默认列分隔符是^A ( ctrl+V 和ctrl+A), 对应的ascii码是'\001'
-- 建表语句如下:
create table if not exists csv1(
uid int,
uname string,
age int,
gender char(1)
); <--------格式都没有指定,默认使用的就是LazySimpleSerde,记录分隔符是\n,列分隔符是^A
-- 可以使用fields terminated by子句来修改默认的列分隔符
drop table csv2;
create table if not exists csv2(
uid int,
uname string,
age int,
gender char(1)
)
row format delimited
fields terminated by '\001'; <------使用^A的ascii码来指定分隔符
-- 可以使用fields terminated by子句来修改默认的列分隔符
create table if not exists csv3(
uid int,
uname string,
age int,
gender char(1)
)
row format delimited
fields terminated by ','; <------告诉SerDe里的方法使用逗号作为分隔符。
2.2 CSVSerDe
-- CSV 是Comma-Separated Values的简写,逗号分隔值,也可以称之字符分隔值
-- CSV 对应的具体SerDe类型是:org.apache.hadoop.hive.serde2.OpenCSVSerde.class
-- 默认列分隔值是逗号
-- 默认行分隔值是\n
-- 常用的三个属性:
1. 默认转义字符(DEFAULT_ESCAPE_CHARACTER): \ <--反斜线
2. 默认引用字符(DEFAULT_QUOTE_CHARACTER): " <--双引号
3. 默认分隔符(DEFAULT_SEPARATOR): , <-逗号
-- 案例演示:使用CSVSerDe
-- 1. 不修改默认列的分隔符建表
drop table csv2;
create table if not exists csv2(
uid int,
uname string,
age int
)
row format serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
;
-- 2. 导入数据
1001,zhangsan,23
1002,lisi,24
1003,wangwu,25
1004,,26
load data local inpath './data/csv2.txt' into table csv2;
--案例演示:修改默认列分隔符的建表形式:
create table csv3(
uid int,
uname string,
age int
)
row format serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
with serdeproperties(
"separatorChar"="7",
"qutoeChar"="'",
"escapeChar"="\\")
stored as textfile
;
--导入数据:
10017zhangsan723
10027lisi724
10037wangwu725
10047726
load data local inpath './data/csv3.txt' overwrite into table csv3;
2.3 JsonSerde
--1. hive本身没有JsonSerDe类型
--2. 可以使用自己编写的,也可以使用第三方的JsonSerDe类型
--3. 在使用JsonSerDe时,应该将jar包加载到classpath下
(1)可以使用add jar临时加载
(2)可以将jar包放入到hive的lib目录下
-- 数据如下:是一个json格式的数据,
{"uid":"1","uname":"gaoyuanyuan","age":"18"}
{"uid":"2","uname":"zhaoyouting","age":"42"}
{"uname":"fanbingbing","uid":"3","age":"42"}
load data local inpath './data/json1.txt' overwrite into table json1;
-- 为上述数据文件,创建表,使用JsonSerDe类型
create table json1(
uid int,
uname string,
age int
)
row format serde 'org.openx.data.jsonserde.JsonSerDe';
JSON的应用场景:复杂类型的使用
--1. 原始数据:
zs math:100,98,76 chinese:98,96,100 english:100,99,90
ls math:60,80,70 chinese:90,66,91 english:50,51,70
-------------------------------------------
create table t1(
uname string,
math map<string,array<int>>,
....
)
row format delimited
fields terminated by ' '
map keys terminiated by ':'
collection items terminated by','
----上述的表语句需要执行map的元素分隔符,还要指定数组的元素分隔符,都用到了collection.
--因此一个collection无法指定多个分割符。这种情况,只能换思路,使用比较合适的serde去导
--入数据(jsonSerde最适合)
-- 清洗数据:
可以使用编程语言转成下面json字符串
{"uname":"zs","score":{"math":[100,98,76],"chinese":[98,96,100],"english":[100,99,90]}}
{"uname":"ls","score":{"math":[60,80,70],"chinese":[90,66,91],"english":[50,51,70]}}
--建表:
create table if not exists complex(
uname string,
score map<String,array<int>>
)
row format serde 'org.openx.data.jsonserde.JsonSerDe'
stored as textfile
;
--导入数据
load data local inpath './data/json2.txt' into table complex;
2.4 RegexSerDe
-- 为什么要提供RegexSerde
因为其他的SerDe都不支持多字符作为分隔符,因此提供了正则SerDe.
-- 正则SerDe对应的具体类型:org.apache.hadoop.hive.serde2.RegexSerDe
--案例演示:
01||zhangsan||23
02||lisi||24
create table if not exists t_regex(
id string,
uname string,
age int,
gender char(1)
)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties(
'input.regex'='(.*)\\|\\|(.*)\\|\\|(.*)\\|\\|(.*)',
'output.format.string'='%1$s %2$s %3$s %4$s'
)
stored as textfile
;
load data local inpath './data/regex.txt' into table t_regex;