赞
踩
-由于hive的基本操作与MySQL大致相同,因此本文不对hive的基本操作进行讲解,而只从hive与MySQL不相同的点出发,对hive进行学习
语法
create database 库名
location 'hdfs_path'
with dbproperties (属性=值) #为数据库指定一定的属性
例子
hive (default)> create database db_hive1 location '/db_hive1' with dbproperties('create_date'='2023-04-14');
hive (default)> desc database extended db_hive1;
OK
db_name comment location owner_name owner_type parameters
db_hive1 hdfs://node1:9000/db_hive1 root USER {create_date=2023-04-14}
语法
DROP DATABASE [IF EXISTS] database_name [restrict | cascade]
restrict:严格模式,只有数据库中没有数据才会被删除,默认q
cascade:级联模式,会连库带表一起删除
用户可以使用 alter database 命令修改数据库某些信息,其中能够修改的信息包括 dbproperties、location、owner user。需要注意的是:修改数据库 location,不会改变当前 已有表的路径信息,而只是改变后续创建的新表的默认的父目录。
语法
alter database 库名set
[dbproperties(...)\
location hdfs_path \
owner user user_name]
create [temporary] [external] table [if not exists]
[库名.]表名
[(列名 数据类型 [comment col_comment], ....)]
[comment table_comment] # 约束
[partitioned by ...] # 分区表
[clustered by ...] # 分桶表
[sorted by ...] # 排序
[row format ...] # 每一行的序列化情况,每一行的解析情况
[stored as ...] # 文件的解析情况
[location hdfs_path] # 表的储存位置
[tblproperties ...] # 表的描述
外部表,与之对应的是内部表(管理表)。管理表以为着hive会全权接管这个表,包括元数据和hdfs数据,而外部表表示hive只会管理元数据。
两者的区别体现在删除时,管理表会将元数据和hdfs中的数据全部删除,而外部表只会删除元数据。
类型 | 说明 | 定义 |
---|---|---|
int | 4byte有符号整数 | |
bigint | 8byte有符号整数 | |
double | 双精度 | |
decimal | 十进制精准数字类型 | decimal(16,2)表示14个整数2个小数 |
varchar | 字符序列,需指定长度 | varchar(32) |
string | 字符串,无需指定长度 | |
array | 数组,类型的集合 | array<string> |
map | 键值对组合 | map<string, int> |
stuct | 结构体 | struct<id:int, name:string> |
结构体:实际上是map的进阶版,map中的value只能由一种类型,而struct中的value可以有多种类型
cast(值 as <type>)
指定,每一行数据的序列化和反序列化形式(serde),即解析每一行的格式
在hive中,没有行数据的读写情况如下:
读数据:HDFS files --> InputFileFormat --> <key, value> --> Deserializer --> Row object
写数据:Row object --> Serializer --> <key, value> --> OutputFileFormat --> HDFS files
对于读数据,由hdfs数据inputfileformat成键值对,然后反序列化称为java的row数据类型。写数据则反之,可见重点在于序列化。
语法
row format delimited # 关键字
[fields terminated by char] # 指定每一列的分隔符号
[collection items terminated by char] # map\struct\array中每一个元素的分隔符号
[map keys terminated by char] # map中key和value的分隔符
[lines terminated by char] # 行分割符
[null defined as char] # null值的定义,默认为 \N
指定文件的存储格式,也指文件解析格式,默认为textfile, 还有sequence file, orc file qarquetfile等等。
例子:查看默认储存文件的行解析格式和列解析格式
hive (default)> show create table stu; createtab_stmt CREATE TABLE `stu`( `id` int, `name` string) ROW FORMAT SERDE # row format情况,即行解析情况 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' STORED AS INPUTFORMAT # stored as 的情况,文件解析情况 'org.apache.hadoop.mapred.TextInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' LOCATION 'hdfs://node1:9000/user/hive/warehouse/stu' TBLPROPERTIES ( 'bucketing_version'='2', 'transient_lastDdlTime'='1681356658') Time taken: 1.242 seconds, Fetched: 14 row(s)
利用select 的返回语句进行建表,与普通建表的区别为,不能建立外表
语法
create [temporary] table [if not exists]
[库名.]表名
[(列名 数据类型 [comment col_comment], ....)]
[comment table_comment] # 约束
[row format ...] # 每一行的序列化情况,每一行的解析情况
[stored as ...] # 文件的解析情况
[location hdfs_path] # 表的储存位置
[tblproperties ...] # 表的描述
[as select_statement]
serde解析使用和复杂数据类型
若有下方json数据类型,其是格式化后的数据,在文件中应该为一行
{ "name": "dasongsong", "friends": [ "bingbing", "lili" ], "students": { "xiaohaihai": 18, "xiaoyangyang": 16 }, "address": { "street": "hui long guan", "city": "beijing", "postal_code": 10010 } }
面对这个数据,我们可以利用hive中自带专门处理json数据的序列化,json serde,然后根据数据情况设计字段。相应字段应该数据保持一致
create table teacher
(
name string,
friends array<string>, # 一级字段需一致
students map<string,int>,
address struct<city:string,street:string,postal_code:int> # 二级字段也一致
)
row format serde 'org.apache.hadoop.hive.serde2.JsonSerDe'
location '/user/hive/warehouse/teacher';
基本语法
select 字段 from 表名
join
where ..
group by ..
having ...
order by ...
cluster by 字段
distribute by 字段
sort by 字段
sort by:局部排序,每一个reduce内部有序
hive中的数据是会通过mr操作的,所以在mr之间会有shuffle的过程,shuffle在合并map结果和合并分区的时候,会根据一个字段进行排序,默认情况下为主键,sort by 用于指定这个字段,使结果使reduce内部有序,而全局不是有序的,但是效率快。order by是将多个reduce聚集在一起然后在排序,因此使全局有序,但是效率慢。
但我们需要全局有序的全体记录时,order by是必不可少的,但如果我们需要是排序的前几个记录时,利用sort by + limit n的操作时最有效的!
例子:
如下图语句,在reduce中预先排序后,只需要从每个reduce中取前10个进行排序即可,比起order by快了很多
# 取工资的前10名。
select * from employees
sort by salary
limit 10;
创建分区表:
create table [external] dept_partition # 创建表 depr_partition
(
列名,
deptno int, --部门编号
dname string, --部门名称
loc string --部门位置
)
partitioned by (day string) # 指定分区字段
row format delimited fields terminated by '\t' # 行解析情况
load
node1>>& vim dept_20220401.log
10 行政部 1700
20 财务部 1800 # 不包含分区字段
load data local inpath './datas/dept_20220401.log'
into table dept_partition
partition(day = '20230416') !!!!
注意:
由上传的数据可以看出,行数据中是不包含分区字段的,但是需要load阶段指定上传数据的partition。
insert
insert [overwrite] table 表名 partition(分区字段)
...
# 例子
insert overwrite table dept_partition partition(day = '20230417') # 指定分区
select * from dept_partition
注意:insert 插入的时候,行数据也不需要包含分区字段,但需要再insert后面指定上传到的partition
读数据时,需要选择分区字段也会字段输出
0: jdbc:hive2://node1:10000> select * from dept_partition;
# 会字段显示分区字段
+-----------------------+-----------------------+---------------------+---------------------+
| dept_partition.depto | dept_partition.dname | dept_partition.loc | dept_partition.day |
+-----------------------+-----------------------+---------------------+---------------------+
| 10 | 行政部 | 1700 | 200111 |
| 20 | 财务部 | 1800 | 200111 |
+-----------------------+-----------------------+---------------------+---------------------+
2 rows selected (1.782 seconds)
hive> show partitions dept_partition
hive (default)>
alter table dept_partition
add partition(day='20220403');
hive (default)>
alter table dept_partition
add partition(day='20220404') partition(day='20220405');
# 单个分区
hive (default)>
alter table dept_partition
drop partition(day='20220403');
# 多个分区之间需要有逗号
hive (default)>
alter table dept_partition
drop partition(day='20220404'), partition(day='20220405');
分区修复指:当元数据记录信息和hdfs中信息不一致时,需要修改元数据形式使两者一致。
注意!修改的是元数据,因为hdfs不归hive管。
当元数据和hdfs路径不一致时,hive访问不到hdfs对应数据,元数据库中的数据映射的是hdfs,因此需要保持一致
语法
hive (default)>
msck repair table table_name [add/drop/sync partitions];
建表
hive (default)>
create table dept_partition2(
deptno int, -- 部门编号
dname string, -- 部门名称
loc string -- 部门位置
)
partitioned by (day string, hour string) # 指定两个字段
row format delimited fields terminated by '\t';
插入
load data local inpath '/opt/module/hive/datas/dept_20220401.log'
into table dept_partition2
partition(day='20220401', hour='12'); # 指定两个字段
(1)动态分区功能总开关(默认true,开启) set hive.exec.dynamic.partition=true (2)严格模式和非严格模式 动态分区的模式,默认strict(严格模式),要求必须指定至少一个分区为静态分区,nonstrict(非严格模式)允许所有的分区字段都使用动态分区。 set hive.exec.dynamic.partition.mode=nonstrict (3)一条insert语句可同时创建的最大的分区个数,默认为1000。 set hive.exec.max.dynamic.partitions=1000 (4)单个Mapper或者Reducer可同时创建的最大的分区个数,默认为100。 set hive.exec.max.dynamic.partitions.pernode=100 (5)一条insert语句可以创建的最大的文件个数,默认100000。 hive.exec.max.created.files=100000 (6)当查询结果为空时且进行动态分区时,是否抛出异常,默认false。 hive.error.on.empty.partition=false
建表:指定以loc 为分区字段
hive (default)>
create table dept_partition_dynamic(
id int,
name string
)
partitioned by (loc int)
row format delimited fields terminated by '\t';
插入语句:
set hive.exec.dynamic.partition.mode = nonstrict;
hive (default)>
insert into table dept_partition_dynamic
partition(loc)
select
deptno,
dname,
loc # !!!!最后一个为分区字段
from dept;
动态分区和普通分区插入的差别在于:动态分区需要在数据的最后一列添加分区字段,相反普通分区不用。
语法:
hive (default)>
create table stu_buck(
id int,
name string
)
clustered by(id) # 分桶字段
into 4 buckets # 指定分桶个数
row format delimited fields terminated by '\t';
hive (default)>
create table stu_buck_sort(
id int,
name string
)
clustered by(id)
sorted by(id) # 排序字段
into 4 buckets
row format delimited fields terminated by '\t';
文章参考B站尚硅谷视频
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。