Hive学习

2020-07-01 00:00:00 数据 模式 删除 分区 分区表

Hive简介

使用SQL来快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,学习成本低,十分适合数据仓库的统计分析。

Hive是基于Hadoop的一个【数据仓库工具】,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。数据仓库是用来查询分析的数据库,基本不用来做修改,删除操作。

Hive架构原理

(1) 用户接口主要有三个:CLI,Client和WUI。

其中常用的是CLI命令行,Cli启动的时候,会同时启动一个Hive副本;

Client是Hive的客户端,用户连接值Hive Server。在启动Client模式的时候,需要指出Hive Server所在节点,并且在该节点启动Hive Server。

WUI是通过浏览器访问Hive。

(2) Hive将元数据存储在数据库中,如mysql、derby。Hive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。

(3) 解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行。

(4) Hive的数据存储在HDFS中,大部分的查询、计算由MapReduce完成(包含*的查询,比如select * from tbl 不会生成MapReduce任务)。

流程:

①HQL通过命令行或者客户端提交到Driver(驱动)

②Driver与Metastore交互找到与表相关的元数据信息

③Compiler解释器编译器转换成MapReduce任务

④Hadoop执行MapReduce任务

Hive 使用ANTLR词法语法分析工具解析hql

①解释器:解释器的作用是将HiveSQL语句转换为抽象语法树(AST)

②编译器:编译器是将语法树编译为逻辑执行计划

③优化器:优化器是对逻辑执行计划进行优化

④执行器:执行器是调用底层的运行框架执行逻辑执行计划

Hive搭建及三种模式

A、内嵌模式(元数据保存在内嵌的derby中,允许一个会话链接,尝试多个会话链接时会报错)

B、单用户模式

安装mysql 替代derby存储元数据

C、远程模式/多用户模式

在服务器端启动MetaStoreServer,客户端利用Thrift协议通过MetaStoreServer访问元数据库

内部表与外部表

外部表:外部关键字EXTERNAL允许您创建一个表,并提供一个位置,以便hive不使用这个表的默认位置。这方便如果你已经生成的数据。当删除一个外部表,表中的数据不是从文件系统中删除。外部表指向任何HDFS的存储位置,而不是存储在配置属性指定的文件夹[hive.metastore.warehouse.dir.]中

内部表 删除连带表中数据一起删除

更新数据

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

删除数据

DELETE FROM tablename [WHERE expression]

注意: 更新和删除需要hive开启ACID机制

四种插入/导入数据

Hive不能很好的支持用insert语句一条一条的进行插入操作,不支持update操作。数据是以load的方式加载到建立好的表中。数据一旦导入就不可以修改。

种:

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

第二种:

创建person2表,然后从表person1.....中导入数据:

INSERT OVERWRITE TABLE person2 [PARTITION(dt='2008-06-08', country)]

SELECT id,name, age From ppt;

第三种:

FROM person t1

INSERT OVERWRITE TABLE person1 [PARTITION(dt='2008-06-08', country)]

SELECT t1.id, t1.name, t1.age ;

【from放前面好处就是后面可以插入多条语句 】

FROM abc t1,sufei t2

INSERT OVERWRITE TABLE qidu

SELECT t1.id,t1.name,t1.age,t1.likes,t1.address

INSERT OVERWRITE TABLE wbb

SELECT t2.id,t2.name,t2.age,t2.likes,t2.address;

注意: 使用多插入模式时,不能插入相同的表

第四种:

本地load数据和从HDFS上load加载数据的过程有什么区别?

本地: local 会自动复制到HDFS上的hive的目录下

Hdfs导入 后移动到hive的目录下

注意:查看用谷歌浏览器 360有时有bug

查询数据并保存

A、保存数据到本地:

例: insert overwrite local directory '/opt/datas/hive_exp_emp2'

ROW FORMAT DELIMITED FIELDS TERMINATED BY ','

select * from db_1128.emp ;

hive命令行中查看linux上的数据:

! cat /opt/datas/hive_exp_emp2/000000_0;

B、保存数据到HDFS上:

例: insert overwrite directory '/user/beifeng/hive/hive_exp_emp'

select * from db_1128.emp ;

hive命令行中查看HDFS上的数据:

dfs -cat /user/beifeng/hive/hive_exp_emp/000000_0;

Hive的group by\join(left join right joinHive的group by\join(left join right join等)\having\sort by \order by等操作和MySQL没有什么大的区别:

Hive分区

Hive的分区partition

假如现在我们公司一天产生3亿的数据量,那么为了方便管理和查询,此时可以建立分区(可按日期 部门等具体业务分区)。分门别类的管理。

注意:可在表定义时创建partition ,也可在以后添加分区

分区分为:单分区和多分区

创建分区

A、单分区建表语句:create table day_table(id int, content string) partitioned by (dt string) row format delimited fields terminated by ',';

【单分区表,如:按天分区,在表结构中存在id,content,dt三列;以dt为文件夹区分】

B、双分区建表语句:create table day_hour_table (id int, content string) partitioned by (dt string, hour string) row format delimited fields terminated by ',';

【双分区表,按天和小时分区,在表结构中新增加了dt和hour两列;先以dt为文件夹,再以hour子文件夹区分】

注意:在创建 删除多分区等操作时一定要注意分区的先后顺序,他们是父子节点的关系。分区字段不要和表字段相同

添加分区表的分区

(表已创建,在此基础上添加分区):

ALTER TABLE table_name ADD partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ...

: ALTER TABLE day_table ADD PARTITION (dt='2008-08-08', hour='08')

删除分区

语法:ALTER TABLE table_name DROP partition_spec, partition_spec,...

– 用户可以用 ALTER TABLE DROP PARTITION 来删除分区。分区的元数据和数据将被一并删除。

例:ALTER TABLE day_hour_table DROP PARTITION (dt='2008-08-08', hour='08');

数据加载进分区表中

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

例: LOAD DATA INPATH '/user/pv.txt' INTO TABLE day_hour_table PARTITION(dt='2008-08-08', hour='08');

LOAD DATA local INPATH '/user/hua/*' INTO TABLE day_hour partition(dt='2010-07- 07');

当数据被加载至表中时,不会对数据进行任何转换。Load操作只是将数据复制至Hive表对应的位置。数据加载时在表下自动创建一个目录基于分区的查询的语句:SELECT day_table.* FROM day_table WHERE day_table.dt >= '2008-08-08';

查看分区语句

hive> show partitions day_hour_table;

重命名分区

ALTER TABLE table_name PARTITION partition_spec RENAME TO PARTITION partition_spec

ALTER TABLE day_table PARTITION (tian='2018-05-01') RENAME TO PARTITION (tain='2018-06-01');

动态分区--注意外部表

1.在本地文件/opt/soft/a.txt中写入以下4行数据: 1 zs 18 bj 2 ls 19 sh 3 cc 20 hz 4 yy 23 bj 5 mm 22 sh 6 lal 17 hz

2.建立非分区表(中间表)并加载数据

create table mid_psn(id int,name string,age int,address string) row format delimited fields terminated by ',';

LOAD DATA LOCAL INPATH '/opt/soft/a.txt' INTO TABLE mid_psn;

3.建立外部分区表并动态加载数据 (注意删除外部表的相关事项)

create table psn(id int, name string,age int) partitioned by (address string) row format delimited fields terminated by ',';

4.将严格模式改为非严格模式: set hive.exec.dynamic.partition.mode=nonstrict;

加载数据到动态分区

from mid_psn insert overwrite table psn partition(address) select id,name,age,address distribute by address;

这时候就需要使用动态分区来实现,使用动态分区需要注意设定以下参数:

hive.exec.dynamic.partition

默认值:false

是否开启动态分区功能,默认false关闭。

使用动态分区时候,该参数必须设置成true;

hive.exec.dynamic.partition.mode

默认值:strict

动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。

一般需要设置为nonstrict

hive.exec.max.dynamic.partitions.pernode

默认值:100

在每个执行MR的节点上,大可以创建多少个动态分区。

该参数需要根据实际的数据来设定。

比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。

hive.exec.max.created.files

默认值:100000

整个MR Job中,大可以创建多少个HDFS文件。

一般默认值足够了,除非你的数据量非常大,需要创建的文件数大于100000,可根据实际情况加以调整。

hive.error.on.empty.partition

默认值:false

当有空分区生成时,是否抛出异常。

一般不需要设置。

Beeline、Hiveserver2与JDBC

Beeline与HiveServer2

服务端 Hiveserver2直接启动

客户端连接服务端的两种方式

1、 beeline -u jdbc:hive2://node5:10000/default -n root

2、 先启动 beeline,然后在交互式界面上使用命令:

​ !connect jdbc:hive2://node5:10000 root 123

Hive的JDBC

一般是平台使用 展示或接口,服务端启动hiveserver2后,在java代码中通过调用hive的jdbc访问默认端口10000进行连接、访问

分桶

分桶表及应用场景

分桶表是对列值取哈希值的方式,将不同数据放到不同文件中存储。

对于hive中每一个表、分区都可以进一步进行分桶。

由列的哈希值除以桶的个数来决定每条数据划分在哪个桶中。

适用场景:

数据抽样( sampling )、map-join

开启支持分桶

set hive.enforce.bucketing=true;

默认:false;设置为true之后,mr运行时会根据bucket的个数自动分配reduce task个数。(用户也可以通过mapred.reduce.tasks自己设置reduce任务个数,但分桶时不推荐使用)

注意:一次作业产生的桶(文件数量)和reduce task个数一致。

往分桶表中加载数据

insert into table bucket_table select columns from tbl;

insert overwrite table bucket_table select columns from tbl;

桶表 抽样查询

select * from bucket_table tablesample(bucket 1 out of 4 on columns);

TABLESAMPLE语法:

TABLESAMPLE(BUCKET x OUT OF y)

x:表示从哪个bucket开始抽取数据

y:必须为该表总bucket数的倍数或因子

创建普通表

例:

CREATE TABLE psn31( id INT, name STRING, age INT) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

测试数据:

1,tom,11

2,cat,22

3,dog,33

4,hive,44

5,hbase,55

6,mr,66

7,alice,77

8,scala,88

创建分桶表

CREATE TABLE psnbucket( id INT, name STRING, age INT)

CLUSTERED BY (age) INTO 4 BUCKETS

ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

加载数据:

insert into table psnbucket select id, name, age from psn31;

抽样

select id, name, age from psnbucket tablesample(bucket 2 out of 4 on age);

相关文章