Hive入门-HQL、表操作、库操作、视图、索引、数据类型【万字详解,倾情打造】

目录

数据类型

库操作

表操作

数据导入导出  

创建表

临时表

内部表

外部表

内外部表转换

分区表

分桶表

查询表

JOIN

修改表

删除表

清空表

特例-update和delete 

视图

视图增删改 

索引

索引原理

索引增删改 

设置自动使用索引

 索引缺陷


数据类型

decimal 类型:

decimal(11,2) 代表最多有 11 位数字,其中后 2 位是小数,整数部分是 9位;如果整数部分超过 9 位,则这个字段就会变成 null;如果小数部分不足 2 位, 则后面用 0 补齐两位,如果小数部分超过两位,则超出部分四舍五入。也可直接写 decimal,后面不指定位数,默认是 decimal(10,0) 整数 10 位,没有小数

 map类型:

zhangsan chinese:90,math:87,english:63,nature:76
lisi chinese:60,math:30,english:78,nature:0
wangwu chinese:89,math:25

create table if not exists map1(
name string,
score map<string,int>)
row format delimited
fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':';


load data local inpath './data/map1.txt' into table map1;


#查询数学⼤于35分的学⽣的英语和⾃然成绩:
select m.name,m.score['english'] ,m.score['nature'] from map1 m
where m.score['math'] > 35;
#查看每个⼈的前两科的成绩总和
select m.name,m.score['chinese']+m.score['math'] from map1 m;

struct类型:

zhangsan 90,87,63,76
lisi 60,30,78,0
wangwu 89,25,81,9


create table if not exists struct1(
name string,
score struct<chinese:int,math:int,english:int,natrue:int>
)
row format delimited
fields terminated by '\t'
collection items terminated by ',';

导⼊数据:
load data local inpath './data/arr1.txt' into table struct1;

select name,score.english,score.chinese from str2
where score.math > 35;

array类型: 

zhangsan    78,89,92,96
lisi    67,75,83,94
王五    23,12


create table if not exists arr1(
    name string,
    scores array<string>
)
row format delimited
fields terminated by '\t'
collection items terminated by ',';

load data local inpath '/data/arr1.txt' into table arr1;
select * from arr1;


#结果
+--------+---------------+
|name    |scores         |
+--------+---------------+
|zhangsan|["78,89,92,96"]|
|lisi    |["67,75,83,94"]|
|王五     |["23,12"]     |
+--------+---------------+

库操作

创建库

CREATE DATABASE [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];

        查询库 

 SHOW DATABASES [LIKE 'identifier_with_wildcards'];

 #注:like通配表达式说明:*表示任意个任意字符,|表示或的关系。

         查看数据库信息

DESCRIBE DATABASE [EXTENDED] db_name;

        修改数据库

用户可以使用alter database命令修改数据库某些信息,其中能够修改的信息包括dbproperties、location、owner user。需要注意的是:修改数据库location,不会改变当前已有表的路径信息,而只是改变后续创建的新表的默认的父目录。

--修改dbproperties

ALTER DATABASE database_name SET DBPROPERTIES (property_name=property_value, ...);

--修改location

ALTER DATABASE database_name SET LOCATION hdfs_path;

--修改owner user

ALTER DATABASE database_name SET OWNER USER user_name;

        删除数据库

DROP DATABASE [IF EXISTS] database_name [RESTRICT|CASCADE];

RESTRICT:严格模式,若数据库不为空,则会删除失败,默认为该模式。

CASCADE:级联模式,若数据库不为空,则会将库中的表一并删除。

       切换当前数据库

USE database_name;

表操作

表有临时表、外部表、内部表(管理表)、分区表,分桶表

Linux上传文件到hdfs上

hdfs dfs -put student.txt

基于其他表的结构建表

create table teacher2 like teacher;

基于查询结果建表

 create table teacher1 as select * from teacher;

数据导入导出  

导入文件到hive表

LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)];

关键字说明:

1)local:表示从本地加载数据到Hive表;否则从HDFS加载数据到Hive表。

2)overwrite:表示覆盖表中已有数据,否则表示追加。

3)partition:表示上传到指定分区,若目标是分区表,需指定分区。

注意!分桶表不能load data,可以先load data到临时表,再从临时表insert from到分桶表

导入表到表

1)create table tbname as select  * from tbname;

2)insert overwrite table tbname select * from tbname;

数据导出

INSERT (INTO | OVERWRITE) TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement;

关键字说明:

1)INTO:将结果追加到目标表

2)OVERWRITE:用结果覆盖原有数据

#导出数据到本地⽂件系统的⽬录下
insert overwrite local directory '/root/out/00'
select * from student;
#导出数据到hdfs的⽬录下
insert overwrite directory '/root/out/01'
select * from student;
#导出的⽂件中字段默认不分隔,修改导出后的列与列之间的格式:
insert overwrite local directory '/root/out/01'
row format delimited fields terminated by ',';
select * from student;

Export&Import

Export导出语句可将表的数据和元数据信息一并到处的HDFS路径,Import可将Export导出的内容导入Hive,表的数据和元数据信息都会恢复。Export和Import可用于两个Hive实例之间的数据迁移。

EXPORT TABLE tablename TO 'export_target_path'

IMPORT TABLE new_or_original_tablename FROM 'source_path' [LOCATION 'import_target_path']

 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]

#行分隔符

 STORED AS参数

指定文件格式,常用的文件格式有,textfile(默认值),sequence file,orc file、parquet file等等。

创建表

临时表

CREATE [TEMPORARY] table if not exist tb_name;

内部表

create table if not exists student(
    id int, 
    name string
)
row format delimited fields terminated by '\t'
location '/user/hive/warehouse/student';
#指定表的数据位置,表删除后,文件也会删除

外部表

create external table if not exists student(
    id int, 
    name string
)
row format delimited fields terminated by '\t'
location '/user/hive/warehouse/student';
#表删除后,文件不会删除

内外部表转换

#内部表转外部表
alter table tableName set tblproperties('EXTERNAL'='TRUE');
注意:内部表转外部表,True⼀定要⼤写;

#外部表转内部表
alter table tableName set tblproperties('EXTERNAL'='false');
说明:false不区分⼤⼩

分区表

#一级分区
create table if not exists part1(
id int,name string,age int)
partitioned by (dt string)
row format delimited
fields terminated by ','
lines terminated by '\n';

#导入数据
load data local inpath './data/user1.txt' 
into table test_ext partition(dt='2020-05-05');



#二级分区
create table if not exists part2(
id int,name string,age int)
partitioned by (year string,month string)
row format delimited
fields terminated by ',';

#导入数据
load data local inpath './data/user1.txt' into table part2
partition(year='2020',month='03');



#三级分区
create table if not exists part3(
id int,name string,age int)
partitioned by (year string,month string,day string)
row format delimited
fields terminated by ',';

#导入数据
load data local inpath './data/user1.txt' into table part3
partition(year='2020',month='05',day='01');
#添加分区
ALTER TABLE tablename 
ADD PARTITION (partition_key='partition_value', ......);
#删除分区
ALTER TABLE tablename DROP 
PARTITION (partition_key='partition_value');
#只是删除元数据,hdfs文件依然保留
#修改分区值
ALTER TABLE tablename 
PARTITION (partition_key='old_partition_value') 
RENAME TO
PARTITION (partition_key='new_partition_value');

注意!

修改分区只会在元数据中修改,不会同步修改HDFS路径,如:

1)原分区路径为: /user/hive/warehouse/test.db/test_table/month=201910 ,分区名: month='201910'

2)将分区名修改为:201911 后,分区所在路径不变,依旧 是:/user/hive/warehouse/test.db/test_table/month=201910

如果希望修改分区名后,同步修改HDFS的路径,并保证正常可用,需要:

1)在元数据库中: 找到SDS表 -> 找到LOCATION列 -> 找到对应分区的路径记录进行修改 如将记录的: /user/hive/warehouse/test.db/test_table/month=201910 修改 为: /user/hive/warehouse/test.db/test_table/month=201911

2)在HDFS中,同步修改文件夹名

如将文件夹: /user/hive/warehouse/test.db/test_table/month=201910 修改为: /user/hive/warehouse/test.db/test_table/month=201911

分桶表

分桶表不能使用load data !!!只能insert .. select ..from

原因:分桶表是要把数据划分成n份,划分规则就是基于分桶列的值进行hash取模来决定,由于load data不会触发mapreduce,没有计算过程,也就是无法执行hash算法,只是简单的移动数据。

Hash取模算法:

同样的值在hash加密后的结果是一致的,不论计算多少次都不会改变。基于这个特征,

假如规定把表划分成3个桶,那么对表的分桶列的字段名进行hash计算,产生的值再%3取模,取模的结果必然是0或1或2,基于取模的结果,把取模结果相同的放到同一个桶中。取模相同的一定在同一文件,同一文件的未必取模都相同。

CREATE TABLE 
course (c_id string,c_name string,t_id string)
[PARTITION(partition_key='partition_value')]
CLUSTERED BY(c_id) INTO 3 BUCKETS 
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';

#分桶表需要开启:
set hive.enforce.bucketing=true;
#设置自动匹配桶数量的reduces task数量
#分桶表不能使用load data

查询表

select  .. from ..
join [tableName] on ..
where ..
group by ..
having ..
order by ..
sort by ..
limit ..
union | union all ...

limit

select * from emp limit 2,3; -- 表示从第2行开始,向下抓取3行

JOIN

由图可知,左外连接(left join)就是以左表为主 ,左表多少行,连接的结果表就多少行,右外连接(right join)同理。满外连接(full outer join)就是左表中有,右表没有的,右表补为NULL,右表中有,左表没有,左表补为NULL,类似于求并集。内连接(inner join)就是求交集,找两张表都有的 

修改表

重命名表

ALTER TABLE table_name RENAME TO new_table_name

增加列

该语句允许用户增加新的列,新增列的位置位于末尾。

ALTER TABLE table_name ADD COLUMNS (col_name data_type [COMMENT col_comment], ...)

更新列

该语句允许用户修改指定列的列名、数据类型、注释信息以及在表中的位置。

ALTER TABLE table_name CHANGE COLUMN col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name]

替换列

该语句允许用户用新的列集替换表中原有的全部列。

ALTER TABLE table_name REPLACE COLUMNS (col_name data_type [COMMENT col_comment], ...)

删除表

DROP TABLE [IF EXISTS] table_name;

清空表

TRUNCATE [TABLE] table_name

注意:truncate只能清空管理表,不能删除外部表中数据。

特例-update和delete 

更新和删除的语法比较简单,和关系型数据库一致。需要注意的是这两个操作都只能在支持 ACID 的表,也就是事务表上才能执行。

-- 更新

UPDATE tablename SET column = value [, column = value ...] [WHERE expression]

--删除

DELETE FROM tablename [WHERE expression]

 需要配置hive-site.xml,开启事务支持,配置完成后重启hive。

<property>
    <name>hive.support.concurrency</name>
    <value>true</value>
</property>
<property>
    <name>hive.enforce.bucketing</name>
    <value>true</value>
</property>
<property>
    <name>hive.exec.dynamic.partition.mode</name>
    <value>nonstrict</value>
</property>
<property>
    <name>hive.txn.manager</name>
    <value>org.apache.hadoop.hive.ql.lockmgr.DbTxnManager</value>
</property>
<property>
    <name>hive.compactor.initiator.on</name>
    <value>true</value>
</property>
<property>
    <name>hive.in.test</name>
    <value>true</value>
</property>

视图

Hive 中的视图和 RDBMS 中视图的概念一致,都是一组数据的逻辑表示,本质上就是一条 SELECT 语句 的结果集。视图是纯粹的逻辑对象,没有关联的存储 (Hive 3.0.0 引入的物化视图除外),当查询引用视 图时,Hive 可以将视图的定义与查询结合起来,例如将查询中的过滤器推送到视图中。

在 Hive 中可以使用 CREATE VIEW 创建视图,如果已存在具有相同名称的表或视图,则会抛出异常, 建议使用 IF NOT EXISTS 预做判断。在使用视图时候需要注意以下事项:

  • 视图是只读的,不能用作 LOAD / INSERT / ALTER 的目标;
  • 在创建视图时候视图就已经固定,对基表的后续更改(如添加列)将不会反映在视图;
  • 删除基表并不会删除视图,需要手动删除视图;
  • 视图可能包含 ORDER BY 和 LIMIT 子句。如果引用视图的查询语句也包含这类子句,其执行优先 级低于视图对应字句。例如,视图 custom_view 指定 LIMIT 5,查询语句为 select * from custom_view LIMIT 10 ,此时结果最多返回 5 行。
  • 创建视图时,如果未提供列名,则将从 SELECT 语句中自动派生列名; 

视图增删改 

创建视图
CREATE VIEW [IF NOT EXISTS] [db_name.]view_name   -- 视图名称
 [(column_name [COMMENT column_comment], ...) ]    --列名
 [COMMENT view_comment]  --视图注释
 [TBLPROPERTIES (property_name = property_value, ...)]  --额外信息
  AS SELECT ...;



查看视图
-- 查看所有视图: 没有单独查看视图列表的语句,只能使用 show tables
show tables;
-- 查看某个视图
desc view_name;
-- 查看某个视图详细信息
desc formatted view_name;


删除视图
DROP VIEW [IF EXISTS] [db_name.]view_name;
-- 删除视图时,如果被删除的视图被其他视图所引用,这时候程序不会发出警告,但是引用该视图其他视
图已经失效,需要进行重建或者删除。


修改视图
ALTER VIEW [db_name.]view_name AS select_statement;
-- 被更改的视图必须存在,且视图不能具有分区,如果视图具有分区,则修改失败。 


修改视图属性
ALTER VIEW [db_name.]view_name SET TBLPROPERTIES (property_name = property_value, property_name = property_value, ...);

示例:
ALTER VIEW custom_view SET TBLPROPERTIES ('create'='heibaiying','date'='2019-05-
05');

索引

Hive 在 0.7.0 引入了索引的功能,索引的设计目标是提高表某些列的查询速度。如果没有索引,带有谓 词的查询(如'WHERE table1.column = 10')会加载整个表或分区并处理所有行。但是如果 column 存在索引,则只需要加载和处理文件的一部分。

索引原理

在指定列上建立索引,会产生一张索引表(表结构如下),里面的字段包括:索引列的值、该值对应的 HDFS 文件路径、该值在文件中的偏移量。在查询涉及到索引字段时,首先到索引表查找索引列值对应 的 HDFS 文件路径及偏移量,这样就避免了全表扫描。

索引增删改 

创建索引
CREATE INDEX index_name     --索引名称
  ON TABLE base_table_name (col_name, ...)  --建立索引的列
  AS index_type    --索引类型
 [WITH DEFERRED REBUILD]    --重建索引
 [IDXPROPERTIES (property_name=property_value, ...)]  --索引额外属性
 [IN TABLE index_table_name]    --索引表的名字
 [
     [ ROW FORMAT ...] STORED AS ...  
     | STORED BY ...
 ]   --索引表行分隔符 、 存储格式
 [LOCATION hdfs_path]  --索引表存储位置
 [TBLPROPERTIES (...)]   --索引表表属性
 [COMMENT "index comment"];  --索引注释



查看索引
--显示表上所有列的索引
SHOW FORMATTED INDEX ON table_name;



删除索引
-- 删除索引会删除对应的索引表。
DROP INDEX [IF EXISTS] index_name ON table_name;
-- 如果存在索引的表被删除了,其对应的索引和索引表都会被删除。如果索引表的某个分区被删除了,
那么分区对应的分区索引也会被删除。


重建索引
ALTER INDEX index_name ON table_name [PARTITION partition_spec] REBUILD;
-- 如果指定了 PARTITION,则仅重建该分区的索引。


查看索引
show index on tb_name;

设置自动使用索引

默认情况下,虽然建立了索引,但是 Hive 在查询时候是不会自动去使用索引的,需要开启相关配置。 开启配置后,涉及到索引列的查询就会使用索引功能去优化查询。

SET hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;

SET hive.optimize.index.filter=true;

SET hive.optimize.index.filter.compact.minsize=0;

 索引缺陷

索引表最主要的一个缺陷在于:索引表无法自动 rebuild,这也就意味着如果表中有数据新增或删除, 则必须手动 rebuild,重新执行 MapReduce 作业,生成索引表数据。 同时按照官方文档 的说明,Hive 会从 3.0 开始移除索引功能,主要基于以下两个原因:

具有自动重写的物化视图 (Materialized View) 可以产生与索引相似的效果(Hive 2.3.0 增加了对 物化视图的支持,在 3.0 之后正式引入)。

使用列式存储文件格式(Parquet,ORC)进行存储时,这些格式支持选择性扫描,可以跳过不需 要的文件或块。

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值