Hive的基本操作
Posted DataFlow范式
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hive的基本操作相关的知识,希望对你有一定的参考价值。
Hive数据类型
TINYINT,SMALLINT,INT,BIGINT,BOOLEAN,FLOAT,DOUBLE,STRING,BINARY,TIMESTAMP,DECIMAL,CHAR,VARCHAR,DATE。
包括ARRAY(数组),MAP(字典),STRUCT(结构体),UNION(联合体),这些复杂类型是由基础类型组成的。
ARRAY:ARRAY类型是由一系列相同数据类型元素组成的,这些元素可以通过下标来访问。比如有一个ARRAY类型的变量fruits,它是由[‘apple’,’orange’,’mango’]组成,那么可以通过fruits[1]来访问orange;
MAP:MAP包含key->value键值对,可以通过key来访问元素。比如”userlist”是一个map类型(其中username是key,password是value),那么我们可以通过userlist[‘username’]来得到这个用户对应的password;
STRUCT:STRUCT可以包含不同数据类型的元素。这些元素可以通过点的方式来得到,比如user是一个STRUCT类型,那么可以通过user.address得到这个用户的地址。
UNION: UNIONTYPE
示例:
Array演示:
create table test
(
name string,
value array<string>
) row format delimited
fields terminated by ‘|‘
collection items terminated by ‘,‘;
文件:array.txt
bigdata|spark,hadoop
warehouse|hive,impala,hbase
load data local inpath ‘/hadoop/ylxsource/myspark/testdata/array.txt‘ into table test;
select name, value[0] from test;
Map演示:
create table test_map(name string, value map<string,int>)
row format delimited
fields terminated by ‘|‘
collection items terminated by ‘,‘
map keys terminated by‘:‘;
文件:map.txt
bigdata|Spark:95,Hadoop:85
warehouse|Hive:80,Impala:70,HBase:90
load data local inpath ‘/hadoop/ylxsource/myspark/testdata/map.txt‘ into table test_map;
select name,value["Spark"] from test_map;
Struct演示:
create table test_struct(id int,name struct<bigdata:string,value:int>)
row format delimited
fields terminated by ‘|‘
collection items terminated by ‘,‘;
文件:struct.txt
1|Spark,100
2|Hive,90
load data local inpath ‘/hadoop/ylxsource/myspark/testdata/struct.txt‘ into table test_struct;
select id, name.bigdata from test_struct;
Union演示:
create table test_union(id int,name map<string,array<string>>)
row format delimited fields terminated by ‘|‘
collection items terminatedby ‘,‘
map keys terminated by‘:‘;
1|Spark:95,10,85
2|Hadoop:85,20,65
Hive文件格式
1. Textfile
Hive默认格式,数据不做压缩,磁盘开销大,数据解析开销大。
可结合Gzip、Bzip2、Snappy等使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
2. Sequencefile
Hadoop API提供的一种二进制文件支持,它将数据(key,value)的形式序列化到文件中,其具有使用方便、可分割、可压缩的特点。SequenceFile支持三种压缩选择:NONE,RECORD,BLOCK。RECORD压缩率低,一般建议使用BLOCK压缩。
3. Rcfile
RCFile是Hive推出的一种专门面向列的数据格式。 它遵循“先按列划分,再垂直划分”的设计理念。
当查询过程中,针对它并不关心的列时,它会在IO上跳过这些列。需要说明的是,RCFile在map阶段从远端拷贝仍然是拷贝整个数据块,并且拷贝到本地目录后,RCFile并不是真正直接跳过不需要的列,并跳到需要读取的列,而是通过扫描每一个row group的头部定义来实现的。
但是在整个HDFS Block 级别的头部并没有定义每个列从哪个row group起始到哪个row group结束。所以在读取所有列的情况下,RCFile的性能反而没有SequenceFile高。
4. ORC
Hive命令行常见操作
l 查看所有数据库
show databases;
l 使用数据库
use hive;
l 查看数据库信息
desc database hive;
l 查看当前使用的数据库
set hive.cli.print.current.db=true;
l 显示列头
set hive.cli.print.header=true;
l 创建数据库
create database hive;
l 删除数据库
drop database hello;
如果数据库不为空,则使用cascade关键字:
drop database IF EXISTS hello cascade;
l 查看数据库的表
show tables;
show tables like ‘*test*‘;
show tables in myspark;
l 获取表信息
show create table test;
desc formatted test;
desc extended test;
l 创建表
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS][db_name.]table_name -- (Note: TEMPORARY available inHive 0.14.0 and later)
[(col_namedata_type [COMMENT col_comment], ...)]
[COMMENTtable_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
[CLUSTEREDBY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTOnum_buckets BUCKETS]
[SKEWEDBY (col_name, col_name,...) -- (Note: Available in Hive 0.10.0 and later)]
ON((col_value, col_value, ...), (col_value, col_value, ...), ...)
[STOREDAS DIRECTORIES]
[
[ROWFORMAT row_format]
[STOREDAS file_format]
|STORED BY ‘storage.handler.class.name‘ [WITH SERDEPROPERTIES (...)] -- (Note: Available inHive 0.6.0 and later)
]
[LOCATIONhdfs_path]
[TBLPROPERTIES(property_name=property_value, ...)] -- (Note: Available inHive 0.6.0 and later)
[ASselect_statement]; -- (Note: Available in Hive 0.5.0 and later; not supported for external tables)
CREATE[TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
LIKEexisting_table_or_view_name
[LOCATION hdfs_path];
data_type
:primitive_type
|array_type
|map_type
|struct_type
|union_type -- (Note: Available in Hive 0.7.0 and later)
primitive_type
:TINYINT
|SMALLINT
|INT
|BIGINT
|BOOLEAN
|FLOAT
|DOUBLE
|STRING
|BINARY -- (Note: Available inHive 0.8.0 and later)
|TIMESTAMP -- (Note: Available in Hive 0.8.0 and later)
|DECIMAL -- (Note: Available inHive 0.11.0 and later)
|DECIMAL(precision, scale) -- (Note: Available inHive 0.13.0 and later)
|DATE -- (Note: Available in Hive 0.12.0 and later)
|VARCHAR -- (Note: Available inHive 0.12.0 and later)
|CHAR -- (Note:Available in Hive 0.13.0 and later)
array_type
:ARRAY < data_type >
map_type
:MAP < primitive_type, data_type >
struct_type
:STRUCT < col_name : data_type [COMMENT col_comment], ...>
union_type
:UNIONTYPE < data_type, data_type, ... > -- (Note: Available inHive 0.7.0 and later)
row_format
:DELIMITED [FIELDS TERMINATED BY char [ESCAPED BY char]] [COLLECTION ITEMS TERMINATED BY char]
[MAPKEYS TERMINATED BY char] [LINES TERMINATED BY char]
[NULLDEFINED AS char] -- (Note: Available in Hive 0.13 and later)
|SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value,property_name=property_value, ...)]
file_format:
:SEQUENCEFILE
|TEXTFILE -- (Default, depending onhive.default.fileformat configuration)
|RCFILE -- (Note: Available inHive 0.6.0 and later)
|ORC -- (Note: Available inHive 0.11.0 and later)
|PARQUET -- (Note: Available inHive 0.13.0 and later)
|AVRO -- (Note:Available in Hive 0.14.0 and later)
|INPUTFORMAT input_format_classname OUTPUTFORMAToutput_format_classname
· 用户可以用 IF NOT EXIST 选项来忽略这个异常。
· EXTERNAL关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION),Hive 创建内部表时,会将数据移动到数据仓库指向的路径;若创建外部表,仅记录数据所在的路径,不对数据的位置做任何改变。在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
· LIKE允许用户复制现有的表结构,但是不复制数据。
· 用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive 通过 SerDe 确定表的具体的列的数据。
· 如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCE 。
· 有分区的表可以在创建的时候使用 PARTITIONED BY 语句。一个表可以拥有一个或者多个分区,每一个分区单独存在一个目录下。而且,表和分区都可以对某个列进行 CLUSTERED BY 操作,将若干个列放入一个桶(bucket)中。也可以利用SORT BY 对数据进行排序。这样可以为特定应用提高性能。
· 表名和列名不区分大小写,SerDe 和属性名区分大小写。表和列的注释是字符串
SerDe是Serialize/Deserilize的简称,目的是用于序列化和反序列化。
l 加载数据
LOAD DATA [LOCAL] INPATH ‘filepath‘ [OVERWRITE]INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
l 创建桶
create table par_table
(
id int,
type string,
value string
)
partitioned by(data_date string, pos string)
clustered by(id) sorted by(value) into 32 buckets
row format delimited
fields terminated by ‘|‘
lines terminated by ‘\n‘
stored as sequencefile;
#强制分桶
set hive.enforce.bucketing = true;
对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
把表(或者分区)组织成桶(Bucket)有两个理由:
1. 获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接(Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
2. 使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
对于Map端连接的情况,两个表以相同方式划分桶。处理左边表内某个桶的 mapper知道右边表内相匹配的行在对应的桶内。因此,mapper只需要获取那个桶 (这只是右边表内存储数据的一小部分)即可进行连接。这一优化方法并不一定要求两个表必须桶的个数相同,两个表的桶个数是倍数关系也可以。
l Hive Client数据操作
hive -help
hive --help
hive -e "use hive;select * from words"
hive -S -e "use hive;select * from words"
hive -f hivecli.sql
hive -S -f hivecli.sql
hive (hive)> source /hadoop/ylxsource/myspark/testdata/hivecli.sql;
hive -S -f hivecli.sql > result.txt
hive (hive)> set val=bigdata;
select * from test where name = ‘${hiveconf:val}‘;
通过sh脚本执行:
test.sh
#!/bin/bash
hive-S -e "
use hive;
select * from test;"
&n
bash test.sh
Hive数据加载(内部表,外部表,分区表)
内部表数据加载
1. 创建表时加载数据
create table test_bak as select * from test;
2. 创建表时指定数据路径
create table if not exists test2(
id int,
name string,
score int
)
row format delimited fields terminated by‘|‘
lines terminated by ‘\n‘
stored as textfile
location ‘file:/hadoop/ylxsource/myspark/testdata/location‘;
表删除时,数据目录也会删除
3. 本地数据加载
create table if not exists test2(
id int,
name string,
score int
)
row format delimited fields terminated by ‘|‘
lines terminated by ‘\n‘
stored as textfile;
load data local inpath ‘/hadoop/ylxsource/myspark/testdata/external.txt‘ into table test2;
4. HDFS数据加载
create table if not exists test2(
id int,
name string,
score int
)
row format delimited fields terminated by ‘|‘
lines terminated by ‘\n‘
stored as textfile;
load data inpath ‘hdfs://SZB-L0007971:28888/testdata/external.txt‘ into table test2;
load data inpath ‘hdfs://SZB-L0007971:28888/testdata/external.txt‘ overwrite into table test2;
5. 通过hdfs命令将数据拷贝到指定的表的目录下面
hdfs dfs -put external.txt hdfs://SZB-L0007971:28888/user/hive/myspark/hive.db/test2/external2.txt
此种方式和内部表相同。
6. 由查询语句加载数据
insert overwrite table test2 select * from test3;
insert into table test2 select * from test3;
外部数据加载
1. 创建外部表时指定分区
create external table if not exists test2(
id int,
name string,
score int
)
row format delimited fields terminated by ‘|‘
lines terminated by ‘\n‘
stored as textfile
location ‘hdfs://SZB-L0007971:28888/testdata/external/‘;
load data inpath ‘hdfs://SZB-L0007971:28888/testdata/external‘ into table test2 partition(dt=20160115);
show partitions test2;
2. 查询时插入数据
drop table IF EXISTS xxx ;
create table IF NOT EXISTS xxx
(
polno stringcomment ‘保单号‘,
plan_code stringcomment ‘险种代码‘,
deptno stringcomment ‘部门‘,
p_number decimal(18) comment ‘人数‘
)
partitioned by (flag string, data_date string)
row format delimited fields terminated by ‘\001‘ ;
insert overwrite table xxx partition(flag, data_date)
select polno,
plan_code,
deptno,
count(distinct insno) as p_number,
‘A1‘ as flag,
‘20160101‘ as data_date
from xxx_tmp
where to_date(undwrt_date) >= ‘2015-12-01‘ and to_date(undwrt_date)< ‘2016-01-01‘
group by polno,
plan_code,
deptno
3. 加载数据到分区表
load data local inpath ‘/home/hadoop/data.txt‘ overwrite into table test partition (ds=‘2013-08-16‘);
load data inpath ‘hdfs://SZB-L0007971:28888/hadoop‘ overwrite into table test partition (ds=‘2013-08-16‘);
Hive数据加载注意问题
分隔符问题:
分隔符默认只有单个字符。如果有多个字符,默认取第一个字符作为分隔符。
数据类型对应问题:
load数据数据,字段类型不能互相转化时,查询结果返回NULL。而实际的数据仍然存在。
select查询插入,字段类型不能互相转化时,插入数据为NULL。而实际的数据也为NULL。
其他:
select查询插入数据,字段值顺序要与表中字段顺序一致,名称可不一致。
Hive在数据加载时不做检查,查询时检查。
外部分区表需要添加分区才能看到数据。
Hive数据导出
使用HDFS命令导出
desc formatted test;获取location路径
使用get方式获取:
hdfs dfs -get hdfs://SZB-L0007971:28888/user/hive/myspark/hive.db/test/array.txtresult.txt
使用text方式获取:
hdfs dfs -text hdfs://SZB-L0007971:28888/user/hive/myspark/hive.db/test/array.txt > ok
通过INSERT … DIRECTORY方式
insert overwrite local directory‘/hadoop/ylxsource/myspark/testdata/test2‘
row format delimited fields terminated by‘\t‘
select * from test2;
insert overwrite directory‘hdfs://SZB-L0007971:28888/testdata/test2‘
row format delimited fields terminated by ‘\t‘
select * from test2;
Shell命令方式
hive -S -e "use hive; select * fromtest2;" > result.txt
第三方工具Sqoop
sqoop import/export
Hive动态分区
动态分区指不需要为不同的分区添加不同的插入语句,分区不确定,需要从数据中自动获取。
相关参数配置
#开启动态分区
set hive.exec.dynamic.partition=true;
#如果模式是strict,则必须有一个静态分区,且放在最前面
set hive.exec.dynamic.partition.mode=nonstrict;
#每个节点生成动态分区最大个数
set hive.exec.max.dynamic.partitions.pernode=10000;
#生成动态分区最大个数,如果自动分区数大于这个参数,将会报错
set hive.exec.max.dynamic.partitions=100000;
#一个任务最多可以创建的文件数目
set hive.exec.max.created.files=150000;
#限定一次最多打开的文件数
set dfs.datanode.max.xcievers=8192;
create table dynamic_table(
id int
)
partitioned by (name string,score string)
row format delimited
fields terminated by ‘\t‘
lines terminated by ‘\n‘
stored as textfile;
insert overwrite table dynamic_table partition(name,score)
select id,name,score from test2;
show partitions dynamic_table;
如果参数set hive.exec.dynamic.partition.mode=strict,则必须指定一个静态分区字段:
set hive.exec.dynamic.partition.mode=strict;
再执行上面的语句:
insert overwrite table dynamic_tablepartition(name,score)
select id,name,score from test2;
会报如下错误:
FAILED: SemanticException [Error 10096]: Dynamic partition strict mode requires at least one staticpartition column. To turn this off sethive.exec.dynamic.partition.mode=nonstrict
需要如下方式指定一个静态分区字段:
insert overwrite table dynamic_table partition(name=‘Bigdata‘,score)
select id,score from test2;
Hive表字段属性修改
l 修改表名
alter table test2 rename to new_test2;
l 添加字段
alter table new_test2 add columns(count1 intcomment ‘count1‘, count2 int comment ‘count2‘);
l 修改字段
create table test_change (a int, b int, c int);
alter table test_change change a a1 int;
alter table test_change change a1 a2 string after b;
alter table test_change change c c1 int first;
l 修改表属性
alter table new_test2 set tblproperties(‘comment‘= ‘this is the table new_test2‘);
l 外部表和内部表互转
内部表转外部表:
alter table new_test2 set TBLPROPERTIES (‘EXTERNAL‘ = ‘TRUE‘);
外部表转内部表:
alter table new_test2 set TBLPROPERTIES(‘EXTERNAL‘=‘FALSE‘);
Hive常见内置函数及其使用
l 查看当前可用函数等信息
show functions;
显示函数的描述信息
DESC FUNCTION concat;
显示函数的扩展描述信息
DESC FUNCTION EXTENDED concat;
l 简单函数
函数的计算粒度为单条记录。
关系运算
数学运算
逻辑运算
数值计算
类型转换
日期函数
条件函数
字符串函数
统计函数
l 聚合函数
函数处理的数据粒度为多条记录。
sum()—求和
count()—求数据量
avg()—求平均直
distinct—求不同值数
min—求最小值
max—求最人值
l 集合函数
复合类型构建
复杂类型访问
复杂类型长度
l 特殊函数
1) 窗口函数
应用场景:
用于分区排序
动态Group By
Top N
累计计算
层次查询
函数:
lead
lag
last_day
last_value
2) 分析函数
RANK
ROW_NUMBER
DENSE_RANK
CUME_DIST
PERCENT_RANK
NTILE
3) 混合函数
java_method(class,method [,arg1 [,arg2])
reflect(class,method [,arg1 [,arg2..]])
hash(a1 [,a2...])
4) UDTF
lateralView: LATERAL VIEW udtf(expression)tableAlias AS columnAlias (‘,‘ columnAlias)*
fromClause: FROM baseTable (lateralView)*
例如:
select t.word_list,count(1) from
(
select word_list from words w lateral viewexplode(split(w.word,‘ ‘)) ww as word_list
) t group by t.word_list;
lateral view用于和split,explode等UDTF一起使用,它能够将一行数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。lateral view首先为原始表的每行调用UDTF,UTDF会把一行拆分成一或者多行,lateral view再把结果组合,产生一个支持别名表的虚拟表。
l 常用函数
1. 获取当前时间
select from_unixtime(unix_timestamp(),‘yyyy-MM-dd HH:mm:ss‘);
2. 截取时间
select regexp_replace(substr(‘2016-01-18‘,0,7),‘-‘,‘‘);
select to_date(‘2016-01-18 12:24:12‘);
3. 修改日期格式
select from_unixtime(to_unix_timestamp(‘2014/6/18‘,‘yyyy/MM/dd‘),‘yyyy-MM-ddHH:mm:ss‘);
4. 数据类型强制转换
select cast(‘1314‘ as int);
5. 判断语句
select ossdkversion,
osversion,
mobilemodel,
carrier,
networkconntype,
org_name,
e_version,
channel,
data_date,
‘登录‘ as module,
case tmp.lable
when ‘用户登陆‘ then ‘用户名+密码登录次数‘
when ‘手势登录成功‘ then ‘手势密码登录成功次数‘
when ‘手势设置失败‘then ‘手势密码设置失败次数‘
when ‘手势登录失败‘ then ‘手势密码登录失败次数‘
when ‘忘记密码‘ then ‘忘记密码‘
end flag
from e_temp tmp
where tmp.lable in (‘用户登陆‘,‘手势登录成功‘,‘手势设置失败‘,‘手势登录失败‘,‘忘记密码‘)
select if(‘o‘=‘o‘,‘o_o‘,‘^o^‘);
6. 解析Json格式内容
selectget_json_object(‘{"name":"spark","age":"10"}‘,‘$.name‘);
7. 解析URL地址
SELECT parse_url(‘http://facebook.com/path/p1.php?query=1‘, ‘HOST‘);
SELECT parse_url(‘http://facebook.com/path/p1.php?query=1‘, ‘QUERY‘)
SELECT parse_url(‘http://facebook.com/path/p1.php?query=1‘,‘QUERY‘, ‘query‘);
8. 字符串连接函数
select concat(‘S‘,‘p‘,‘a‘,‘r‘,‘k‘);
select concat_ws(‘-‘,‘S‘,‘p‘,‘a‘,‘r‘,‘k‘);
9. 输出数组集合
列出该字段所有不重复的值,相当于去重
collect_set(polno) //返回的是数组
列出该字段所有的值,列出来不去重
collect_list(polno) //返回的是数组
select collect_set(polno) from myspark.pol_ben_s;
select collect_list(polno) from myspark.pol_ben_s;
10. 窗口函数:
first_value:
select polno,certno,first_value(certno) over (partition bypolno order by certno desc ) from myspark.pol_ben_s;
rank:
select polno,certno, rank() over (partition by polno order bycertno) as rank from myspark.pol_ben_s;
row_number:
select polno,certno, row_number() over (partition by polnoorder by certno) as rank from myspark.pol_ben_s;
row_number()是没有重复值的排序(即使两天记录相等也是不重复的),可以利用它来实现分页
dense_rank()是连续排序,两个第二名仍然跟着第三名
rank()是跳跃拍学,两个第二名下来就是第四名
11. 使用正则表达式
select regexp_extract(‘x=a3&x=18abc&x=2&y=3&x=4‘,‘x=([0-9]+)([a-z]+)‘,0);
select regexp_extract(‘x=a3&x=18abc&x=2&y=3&x=4‘,‘x=([0-9]+)([a-z]+)‘,1);
select regexp_extract(‘x=a3&x=18abc&x=2&y=3&x=4‘,‘x=([0-9]+)([a-z]+)‘,2);
以上是关于Hive的基本操作的主要内容,如果未能解决你的问题,请参考以下文章