文章目录
- Hive提高篇
-
- Hive的使用
-
- Hive的分桶表
-
- 1. 分桶表的原理
- 2. 分桶表的作用
- 3. 案例演示
- Hive数据导入
-
- 1. 直接向表中插入数据(强烈不推荐使用)
- 2. 通过load加载数据(必须掌握)
- 3. 通过查询加载数据(必须掌握)
- 4. 查询语句中创建表并加载数据(as select)
- 5. 创建表时指定location
- 6. export导出与import 导入 hive表数据(内部表操作)
- Hive数据导出
-
- 1. insert 导出
- 2. Hive Shell 命令导出 (需要在linux终端执行)
- 3 export导出到HDFS上
- Hive的静态分区和动态分区
-
- Hive的查询语法
-
- 1. 基本查询
- 2. 分组
- 3. join语句
- 4. 排序
- Hive表的数据压缩
-
- 1. 数据压缩对比
- 2. 压缩配置参数
- 3. 开启Map输出阶段压缩
- 4. 开启Reduce输出阶段压缩
- Hive表的文件存储格式
-
- 1. 列式存储和行式存储
- 2. TEXTFILE格式
- 3. ORC格式
- 4. PARQUET格式 (impala)
- 5. 主流文件存储格式对比实验
-
- TextFile
- ORC
- Parquet
- 存储文件的查询速度测试
- 存储和压缩结合
-
- 1. 创建一个非压缩的的ORC存储方式
- 2. 创建一个SNAPPY压缩的ORC存储方式
- 3. 企业实战
-
- 通过MultiDelimitSerDe 解决多字符分割场景
- 通过RegexSerDe 解决多字符分割场景
Hive提高篇
Hive的使用
Hive的分桶表
1. 分桶表的原理
- 分桶是相对分区进行更细粒度的划分,Hive表或分区表可进一步的分桶
- 分桶将整个数据内容按照某列取hash值,对桶的个数取模的方式决定该条记录存放在哪个桶当中;具有相同hash值的数据进入到同一个文件中
- 比如按照name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。
- 取模结果为0的数据记录存放到一个文件
- 取模结果为1的数据记录存放到一个文件
- 取模结果为2的数据记录存放到一个文件
2. 分桶表的作用
- 取样sampling更高效。没有分桶的话需要扫描整个数据集。
- 提升某些查询操作效率,例如map side join。
3. 案例演示
set hive.enforce.bucketing=true;
set mapreduce.job.reduces=4;
use myhive;
create table user_buckets_demo(id int, name string)
clustered by(id)
into 4 buckets
row format delimited fields terminated by '\t';
create table user_demo(id int, name string)
row format delimited fields terminated by '\t';
1 anzhulababy1
2 anzhulababy2
3 anzhulababy3
4 anzhulababy4
5 anzhulababy5
6 anzhulababy6
7 anzhulababy7
8 anzhulababy8
9 anzhulababy9
10 anzhulababy10
load data local inpath '/bigdata/install/hivedatas/user_bucket.txt' overwrite into table user_demo;
insert into table user_buckets_demo select * from user_demo;
hive3.x版本之后, 可以直接向分桶表中load数据即可, 不需要通过insert … select 语句像分桶表插入数据的方式来进行分桶
注意: 希望load能够直接分桶, 需要从hdfs上load文件, 不能从本地load
load data inpath '/user/hive/warehouse/myhive.db/user_demo' overwrite into table myhive.user_buckets_demo;
Hive数据导入
1. 直接向表中插入数据(强烈不推荐使用)
hive (myhive)> create table score3 like score;
hive (myhive)> insert into table score3 partition(month = '201807') values('001', '002', '100');
2. 通过load加载数据(必须掌握)
load data [local] inpath 'dataPath' [overwrite] into table student [partition(partcol1=val1,…)];
hive (myhive)> load data local inpath '/bigdata/install/hivedatas/score.csv' into table score partition(month='201806');
3. 通过查询加载数据(必须掌握)
INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] select_statement1 FROM from_statement;
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement;
hive (myhive)> create table score5 like score;
hive (myhive)> insert overwrite table score5 partition(month = '201806') select s_id,c_id,s_score from score;
4. 查询语句中创建表并加载数据(as select)
hive (myhive)> create table score6 as select * from score;
5. 创建表时指定location
hive (myhive)> create external table score7 (s_id string,c_id string,s_score int) row format delimited fields terminated by '\t' location '/myscore7';
- 上传数据到hdfs上,我们也可以直接在hive客户端下面通过dfs命令来进行操作hdfs的数据
hive (myhive)> dfs -mkdir -p /myscore7;
hive (myhive)> dfs -put /bigdata/install/hivedatas/score.csv /myscore7;
hive (myhive)> select * from score7;
6. export导出与import 导入 hive表数据(内部表操作)
hive (myhive)> create table teacher2 like teacher;
hive (myhive)> export table teacher to '/user/teacher';
hive (myhive)> import table teacher2 from '/user/teacher';
Hive数据导出
1. insert 导出
INSERT OVERWRITE [LOCAL] DIRECTORY directory1
[ROW FORMAT row_format] [STORED AS file_format] (Note: Only available starting with Hive 0.11.0)
SELECT ... FROM ...
insert overwrite local directory '/bigdata/install/hivedatas/stu1' select * from stu1;
insert overwrite local directory '/bigdata/install/hivedatas/stu1' row format delimited fields terminated by ',' select * from stu1;
- 将查询的结果导出到HDFS上==(没有local)==
insert overwrite directory '/bigdata/install/hivedatas/stu' row format delimited fields terminated by ',' select * from stu;
2. Hive Shell 命令导出 (需要在linux终端执行)
hive -e "sql语句" > file
hive -f sql文件 > file
- 在linux命令行中,运行如下命令,导出 myhive.stu 表的数据到本地磁盘文
hive -e 'select * from myhive.stu;' > /bigdata/install/hivedatas/student1.txt;
3 export导出到HDFS上
export table myhive.stu to '/bigdata/install/hivedatas/stuexport';
Hive的静态分区和动态分区
1. 静态分区
- 表的分区字段的值需要开发人员手动给定
- 数据文件 order.txt
10001 100 2019-03-02
10002 200 2019-03-02
10003 300 2019-03-02
10004 400 2019-03-03
10005 500 2019-03-03
10006 600 2019-03-03
10007 700 2019-03-04
10008 800 2019-03-04
10009 900 2019-03-04
use myhive;
create table order_partition(
order_number string,
order_price double,
order_time string
)
partitioned BY(month string)
row format delimited fields terminated by '\t';
load data local inpath '/bigdata/install/hivedatas/order.txt' overwrite into table order_partition partition(month='2019-03');
hive (myhive)> select * from order_partition where month='2019-03';
OK
order_partition.order_number order_partition.order_price order_partition.order_time order_partition.month
10001 100.0 2019-03-02 2019-03
10002 200.0 2019-03-02 2019-03
10003 300.0 2019-03-02 2019-03
10004 400.0 2019-03-03 2019-03
10005 500.0 2019-03-03 2019-03
10006 600.0 2019-03-03 2019-03
10007 700.0 2019-03-04 2019-03
10008 800.0 2019-03-04 2019-03
10009 900.0 2019-03-04 2019-03
Time taken: 2.511 seconds, Fetched: 9 row(s)
2. 动态分区
- 按照需求实现把数据自动导入到表的相应分区中,不需要手动指定分区字段的值
- 需求:根据分区字段不同的值,自动将数据导入到分区表不同的分区中
- 数据文件 order_partition.txt
10001 100 2019-03-02
10002 200 2019-03-02
10003 300 2019-03-02
10004 400 2019-03-03
10005 500 2019-03-03
10006 600 2019-03-03
10007 700 2019-03-04
10008 800 2019-03-04
10009 900 2019-03-04
create table t_order(
order_number string,
order_price double,
order_time string
)row format delimited fields terminated by '\t';
create table order_dynamic_partition(
order_number string,
order_price double
)partitioned BY(order_time string)
row format delimited fields terminated by '\t';
load data local inpath '/bigdata/install/hivedatas/order_partition.txt' overwrite into table t_order;
hive> set hive.exec.dynamic.partition=true;
hive> set hive.exec.dynamic.partition.mode=nonstrict;
hive> insert into table order_dynamic_partition partition(order_time) select order_number, order_price, order_time from t_order;
hive (myhive)> show partitions order_dynamic_partition;
OK
partition
order_time=2019-03-02
order_time=2019-03-03
order_time=2019-03-04
Time taken: 0.154 seconds, Fetched: 3 row(s)
hive3.x之后, 可以直接通过load的方式导入hdfs上的文件完成动态分区, 并且不需要做任何属性设置, 动态分区会根据最后一个字段来进行分区
load data inpath '/user/hive/warehouse/myhive.db/t_order' overwrite into table myhive.order_dynamic_partition;
Hive的查询语法
1. 基本查询
- SQL 语言大小写不敏感,SQL 可以写在一行或者多行
- 关键字不能被缩写也不能分行,各子句一般要分行写,使用缩进提高语句的可读性
select * from stu;
select id, name from stu;
select id, name as stuName from stu;
select count(*) from stu;
select max(s_score) from score;
select min(s_score) from score;
select sum(s_score) from score;
select avg(s_score) from score;
select * from score limit 5;
select * from score where s_score > 60;
运算符 |
描述 |
A+B |
A和B 相加 |
A-B |
A减去B |
A*B |
A和B 相乘 |
A/B |
A除以B |
A%B |
A对B取余 |
A&B |
A和B按位取与 |
A|B |
A和B按位取或 |
A^B |
A和B按位取异或 |
~A |
A按位取反 |
操作符 |
支持的数据类型 |
描述 |
A=B |
基本数据类型 |
如果A等于B则返回true,反之返回false |
A<=>B |
基本数据类型 |
如果A和B都为NULL,则返回true,其他的和等号(=)操作符的结果一致,如果任一为NULL则结果为NULL |
A<>B, A!=B |
基本数据类型 |
A或者B为NULL则返回NULL;如果A不等于B,则返回true,反之返回false |
A
| 基本数据类型 |
A或者B为NULL,则返回NULL;如果A小于B,则返回true,反之返回false |
A<=B |
基本数据类型 |
A或者B为NULL,则返回NULL;如果A小于等于B,则返回true,反之返回false |
A>B |
基本数据类型 |
A或者B为NULL,则返回NULL;如果A大于B,则返回true,反之返回false |
A>=B |
基本数据类型 |
A或者B为NULL,则返回NULL;如果A大于等于B,则返回true,反之返回false |
A [NOT] BETWEEN B AND C |
基本数据类型 |
如果A,B或者C任一为NULL,则结果为NULL。如果A的值大于等于B而且小于或等于C,则结果为true,反之为false。如果使用NOT关键字则可达到相反的效果。 |
A IS NULL |
所有数据类型 |
如果A等于NULL,则返回true,反之返回false |
A IS NOT NULL |
所有数据类型 |
如果A不等于NULL,则返回true,反之返回false |
IN(数值1, 数值2) |
所有数据类型 |
使用 IN运算显示列表中的值 |
A [NOT] LIKE B |
STRING 类型 |
B是一个SQL下的简单正则表达式,如果A与其匹配的话,则返回true;反之返回false。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果。like不是正则,而是通配符 |
A RLIKE B, A REGEXP B |
STRING 类型 |
B是一个正则表达式,如果A与其匹配,则返回true;反之返回false。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。 |
操作符 |
操作 |
描述 |
A AND B |
逻辑并 |
如果A和B都是true则为true,否则false |
A OR B |
逻辑或 |
如果A或B或两者都是true则为true,否则false |
NOT A |
逻辑否 |
如果A为false则为true,否则false |
2. 分组
select s_id, avg(s_score) from score group by s_id;
select s_id, max(s_score) from score group by s_id;
select s_id, avg(s_score) from score group by s_id;
select s_id, avg(s_score) as avgScore from score group by s_id having avgScore > 60;
select s_id, avg(s_score) as avgScore from score group by s_id having avg(s_score) > 60;
3. join语句
- Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接。
- 等值 join
select * from stu left join score on stu.id = score.s_id;
create table course (c_id string, c_name string, t_id string)
row format delimited fields terminated by '\t';
load data local inpath '/bigdata/install/hivedatas/course.csv' overwrite into table course;
select * from teacher t join course c on t.t_id = c.t_id;
- 内连接 inner join:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来。
select * from teacher t inner join course c on t.t_id = c.t_id;
- 左外连接 left outer join:join操作符左边表中符合where子句的所有记录将会被返回,右边表的指定字段没有符合条件的值的话,那么就使用null值替代。
select * from teacher t left outer join course c on t.t_id = c.t_id;
select * from teacher t right outer join course c on t.t_id = c.t_id;
- 满外连接 full outer join:将会返回所有表中符合where语句条件的所有记录,如果任一表的指定字段没有符合条件的值的话,那么就使用null值替代。
select * from teacher t full outer join course c on t.t_id = c.t_id;
- 多表连接:连接 n个表,至少需要n-1个连接条件。例如:连接三个表,至少需要两个连接条件。
select * from products p
left join brands b on p.brand_id = b.id
left join categorys c on p.category_id = c.id;
4. 排序
select * from score s order by s_score desc;
s.s_id s.c_id s.s_score s.month
01 03 99 201806
07 03 98 201806
01 02 90 201806
07 02 89 201806
05 02 87 201806
03 03 80 201806
03 02 80 201806
03 01 80 201806
02 03 80 201806
01 01 80 201806
05 01 76 201806
02 01 70 201806
02 02 60 201806
04 01 50 201806
06 03 34 201806
06 01 31 201806
04 02 30 201806
04 03 20 201806
select s_id, avg(s_score) avgscore from score group by s_id order by avgscore desc;
s_id avgscore
07 93.5
01 89.66666666666667
05 81.5
03 80.0
02 70.0
04 33.333333333333336
06 32.5
- 每个MapReduce内部排序(Sort By)局部排序:每个reducer内部有序排序(局部有序),对全局结果集来说并非全局有序。
set mapreduce.job.reduces=3;
set mapreduce.job.reduces;
select * from score s sort by s.s_score;
insert overwrite local directory '/bigdata/install/hivedatas/sort' select * from score s sort by s.s_score;
- distribute by 分区排序:类似MR中partition,采集hash算法,在map端将查询的结果中hash值相同的结果分发到对应的reduce文件中。
- 结合sort by使用;
- Hive要求 distribute by 语句要写在 sort by 语句之前。
set mapreduce.job.reduces=3;
insert overwrite local directory '/bigdata/install/hivedatas/distribute' select * from score distribute by s_id sort by s_score;
- cluster by:当distribute by和sort by字段相同时,可以使用cluster by方式代替
- 除了distribute by 的功能外,还会对该字段进行排序,所以cluster by s_score = distribute by s_score + sort by s_score
insert overwrite local directory '/bigdata/install/hivedatas/distribute_sort' select * from score distribute by s_score sort by s_score;
insert overwrite local directory '/bigdata/install/hivedatas/cluster' select * from score cluster by s_score;
Hive表的数据压缩
1. 数据压缩对比
-
压缩模式评价:
- 压缩比:压缩比越高,压缩后文件越小,所以压缩比越高越好
- 压缩时间:越快越好
- 是否可分割:可以分割的格式允许单一文件由多个Mapper程序处理,可以更好的并行化
-
常见压缩格式
压缩方式 |
压缩比 |
压缩速度 |
解压缩速度 |
是否可分割 |
gzip |
13.4% |
21 MB/s |
118 MB/s |
否 |
bzip2 |
13.2% |
2.4MB/s |
9.5MB/s |
是 |
lzo |
20.5% |
135 MB/s |
410 MB/s |
否 |
snappy |
22.2% |
172 MB/s |
409 MB/s |
否 |
压缩格式 |
对应的编码/解码器 |
DEFLATE |
org.apache.hadoop.io.compress.DefaultCodec |
Gzip |
org.apache.hadoop.io.compress.GzipCodec |
BZip2 |
org.apache.hadoop.io.compress.BZip2Codec |
LZO |
com.hadoop.compress.lzo.LzopCodec |
Snappy |
org.apache.hadoop.io.compress.SnappyCodec |
压缩算法 |
原始文件大小 |
压缩文件大小 |
压缩速度 |
解压速度 |
gzip |
8.3GB |
1.8GB |
17.5MB/s |
58MB/s |
bzip2 |
8.3GB |
1.1GB |
2.4MB/s |
9.5MB/s |
LZO |
8.3GB |
2.9GB |
49.3MB/s |
74.6MB/s |
2. 压缩配置参数
- 要在Hadoop中启用压缩,可以配置如下参数(mapred-site.xml文件中):
参数 |
取值 |
阶段 |
建议 |
io.compression.codecs(在core-site.xml中配置) |
org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec, org.apache.hadoop.io.compress.Lz4Codec |
输入压缩 |
Hadoop使用文件扩展名判断是否支持某种编解码器 |
mapreduce.map.output.compress |
true |
mapper输出 |
这个参数设为true启用压缩 |
mapreduce.map.output.compress.codec |
org.apache.hadoop.io.compress.DefaultCodec |
mapper输出 |
使用LZO、LZ4或snappy编解码器在此阶段压缩数据 |
mapreduce.output.fileoutputformat.compress |
true |
reducer输出 |
这个参数设为true启用压缩 |
mapreduce.output.fileoutputformat.compress.codec |
org.apache.hadoop.io.compress. DefaultCodec |
reducer输出 |
使用标准工具或者编解码器,如gzip和bzip2 |
mapreduce.output.fileoutputformat.compress.type |
NONE|RECORD |
reducer输出 |
SequenceFile输出使用的压缩类型:NONE和BLOCK |
3. 开启Map输出阶段压缩
- 开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量。具体配置如下:
hive (default)> set hive.exec.compress.intermediate=true;
hive (default)> set mapreduce.map.output.compress=true;
hive (default)> set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;
hive (default)> select count(1) from score;
4. 开启Reduce输出阶段压缩
- 当Hive将输出写入到表中时,输出内容同样可以进行压缩。属性
hive.exec.compress.output
控制着这个功能。用户可能需要保持默认设置文件中的默认值false,这样默认的输出就是非压缩的纯文本文件了。用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出结果压缩功能。
hive (default)>set hive.exec.compress.output=true;
hive (default)>set mapreduce.output.fileoutputformat.compress=true;
hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
hive (default)>set mapreduce.output.fileoutputformat.compress.type=BLOCK;
insert overwrite local directory '/bigdata/install/hivedatas/snappy'
select * from teacher;
Hive表的文件存储格式
- Hive支持的存储数据的格式主要有:TEXTFILE(行式存储) 、SEQUENCEFILE(行式存储)、ORC(列式存储)、PARQUET(列式存储)。
1. 列式存储和行式存储
- 上图左边为逻辑表,右边第一个为行式存储,第二个为列式存储。
- **行存储的特点:**查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的每个列的值,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。
- 列存储的特点:
- 因为每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量;
- 每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。 select 某些字段效率更高。
- TEXTFILE和SEQUENCEFILE的存储格式都是基于行存储的,ORC和PARQUET是基于列式存储的。
2. TEXTFILE格式
- 默认格式,数据不做压缩,磁盘开销大,数据解析开销大。可结合Gzip、Bzip2使用(系统自动检查,执行查询时自动解压),但使用gzip方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
3. ORC格式
- Orc (Optimized Row Columnar)是hive 0.11版里引入的新的存储格式。
- 可以看到每个Orc文件由1个或多个stripe组成,每个stripe250MB大小,这个Stripe实际相当于RowGroup概念,不过大小由4MB->250MB,这样能提升顺序读的吞吐率。每个Stripe里有三部分组成,分别是 Index Data、Row Data、Stripe Footer:
- 一个orc文件可以分为若干个Stripe,一个stripe可以分为三个部分:
- IndexData:某些列的索引数据。一个轻量级的index,默认是每隔1W行做一个索引。这里做的索引只是记录某行的各字段在Row Data中的offset。
- RowData:真正的数据存储。存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个Stream来存储。
- StripFooter:存的是各个stripe的元数据信息。
- 每个文件有一个File Footer,这里面存的是每个Stripe的行数,每个Column的数据类型信息等。
- 每个文件的尾部是一个PostScript,这里面记录了整个文件的压缩类型以及FileFooter的长度信息等。在读取文件时,会seek到文件尾部读PostScript,从里面解析到File Footer长度,再读FileFooter,从里面解析到各个Stripe信息,再读各个Stripe,即从后往前读。
4. PARQUET格式 (impala)
- Parquet是面向分析型业务的列式存储格式,由Twitter和Cloudera合作开发,2015年5月从Apache的孵化器里毕业成为Apache顶级项目。
- Parquet文件是以二进制方式存储的,所以是不可以直接读取的,文件中包括该文件的数据和元数据,因此Parquet格式文件是自解析的。
- 通常情况下,在存储Parquet数据的时候会按照Block大小设置行组的大小,由于一般情况下每一个Mapper任务处理数据的最小单位是一个Block,这样可以把每一个行组由一个Mapper任务处理,增大任务执行并行度。Parquet文件的格式如下图所示。
- 上图展示了一个Parquet文件的内容,一个文件中可以存储多个行组,文件的首位都是该文件的Magic Code,用于校验它是否是一个Parquet文件,Footer length记录了文件元数据的大小,通过该值和文件长度可以计算出元数据的偏移量,文件的元数据中包括每一个行组的元数据信息和该文件存储数据的Schema信息。除了文件中每一个行组的元数据,每一页的开始都会存储该页的元数据,在Parquet中,有三种类型的页:数据页、字典页和索引页。数据页用于存储当前行组中该列的值,字典页存储该列值的编码字典,每一个列块中最多包含一个字典页,索引页用来存储当前行组下该列的索引,目前Parquet中还不支持索引页。
5. 主流文件存储格式对比实验
- 从存储文件的压缩比和查询速度两个角度对比。
- 测试数据:https://download.csdn.net/download/yangwei234/58301049
TextFile
use myhive;
create table log_text (
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE;
load data local inpath '/bigdata/install/hivedatas/log.data' into table log_text;
dfs -du -h /user/hive/warehouse/myhive.db/log_text;
ORC
create table log_orc(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS orc ;
insert into table log_orc select * from log_text ;
dfs -du -h /user/hive/warehouse/myhive.db/log_orc;
- orc这种存储格式,默认使用了zlib压缩方式来对数据进行压缩,所以数据会变成了2.8M,非常小
Parquet
create table log_parquet(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS PARQUET ;
insert into table log_parquet select * from log_text ;
dfs -du -h /user/hive/warehouse/myhive.db/log_parquet;
ORC > Parquet > textFile
存储文件的查询速度测试
select count(*) from log_text;
select count(*) from log_orc;
select count(*) from log_parquet;
Parquet > ORC > TextFile
存储和压缩结合
Key |
Default |
Notes |
orc.compress |
ZLIB |
high level compression (one of NONE, ZLIB, SNAPPY) |
orc.compress.size |
262,144 |
number of bytes in each compression chunk;256kB |
orc.stripe.size |
67,108,864 |
number of bytes in each stripe |
orc.row.index.stride |
10,000 |
number of rows between index entries (must be >= 1000) |
orc.create.index |
true |
whether to create row indexes |
orc.bloom.filter.columns |
“” |
comma separated list of column names for which bloom filter should be created |
orc.bloom.filter.fpp |
0.05 |
false positive probability for bloom filter (must >0.0 and <1.0) |
1. 创建一个非压缩的的ORC存储方式
create table log_orc_none(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS orc tblproperties ("orc.compress"="NONE");
insert into table log_orc_none select * from log_text ;
dfs -du -h /user/hive/warehouse/myhive.db/log_orc_none;
2. 创建一个SNAPPY压缩的ORC存储方式
create table log_orc_snappy(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
STORED AS orc tblproperties ("orc.compress"="SNAPPY");
insert into table log_orc_snappy select * from log_text ;
dfs -du -h /user/hive/warehouse/myhive.db/log_orc_snappy ;
- 上一节中默认创建的ORC存储方式,导入数据后的大小为
2.8 M 8.3 M /user/hive/warehouse/myhive.db/log_orc/000000_0
- 比Snappy压缩的还小:原因是orc存储文件默认采用ZLIB压缩,比snappy压缩的小。
- 存储方式和压缩总结:在实际的项目开发当中,hive表的数据存储格式一般选择 orc 或 parquet,压缩方式一般选择snappy。
3. 企业实战
通过MultiDelimitSerDe 解决多字符分割场景
- 官网建表语法参考
- MultiDelimitSerDe参考
- 测试数据文件 t1.txt
1##xiaoming
2##xiaowang
3##xiaozhang
create table t1 (id String, name string)
row format serde 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe'
WITH SERDEPROPERTIES ("field.delim"="##");
load data local inpath '/bigdata/install/hivedatas/t1.txt' into table t1;
select * from t1;
+
| t1.id | t1.name |
+
| 1 | xiaoming |
| 2 | xiaowang |
| 3 | xiaozhang |
+
通过RegexSerDe 解决多字符分割场景
create table t2(id int, name string)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
WITH SERDEPROPERTIES ("input.regex" = "^(.*)\\#\\#(.*)$");
load data local inpath '/bigdata/install/hivedatas/t1.txt' into table t2;
select * from t2;
+
| t2.id | t2.name |
+
| 1 | xiaoming |
| 2 | xiaowang |
| 3 | xiaozhang |
+