文章目录
一、基本概念
1、什么是Hive
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。
本质:将HQL转化成MapReduce程序
- Hive处理的数据存储到HDFS
- Hive分析数据底层实现的是MapReduce
- 执行程序运行在yarn上
2、Hive的优缺点
优点
1)操作接口采用类SQL语法,提供快速开发的能力(简单、容易上手)
2)避免了去写MapReduce,减少开发人员的学习成本。
3)Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要求不高的场合;
4)Hive优势在于处理大数据,对于处理小数据没有优势,因为Hive的执行延迟比较高。
5)Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
缺点
1)Hive的HQL表达能力有限(迭代算法无法表达、数据挖掘方面不擅长)
2)Hive的效率比较低(Hive自动生成的MapReduce作业,通常情况下不够智能化;调优比较困难且粒度较粗)
3、Hive架构原理
如图中所示,Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后,将执行返回的结果输出到用户交互接口。
1)用户接口:Client
CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问hive)
2)元数据:Metastore
元数据包括:表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等;
默认存储在自带的derby数据库中,推荐使用MySQL存储Metastore
3)Hadoop
使用HDFS进行存储,使用MapReduce进行计算。
4)驱动器:Driver
(1)解析器(SQL Parser):将SQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
(2)编译器(Physical Plan):将AST编译生成逻辑执行计划。
(3)优化器(Query Optimizer):对逻辑执行计划进行优化。
(4)执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于Hive来说,就是MR/Spark。
4、Hive和数据库对比
由于Hive采用了类似SQL的查询语言 HQL(Hive Query Language),因此很容易将Hive理解为数据库。其实从结构上来看,Hive和数据库除了拥有类似的查询语言,再无类似之处。本文将从多个方面来阐述Hive和数据库的差异。数据库可以用在Online的应用中,但是Hive是为数据仓库而设计的,清楚这一点,有助于从应用角度理解Hive的特性。
1、数据存储位置
Hive 是建立在 Hadoop 之上的,所有 Hive 的数据都是存储在 HDFS 中的。而数据库则可以将数据保存在块设备或者本地文件系统中。
2、数据更新
由于Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive中不支持对数据的改写和添加,所有的数据都是在加载的时候确定好的。而数据库中的数据通常是需要经常进行修改的,因此可以使用 INSERT INTO … VALUES 添加数据,使用 UPDATE … SET修改数据。
3、索引
Hive在加载数据的过程中不会对数据进行任何处理,甚至不会对数据进行扫描,因此也没有对数据中的某些Key建立索引。Hive要访问数据中满足条件的特定值时,需要暴力扫描整个数据,因此访问延迟较高。由于MapReduce 的引入, Hive可以并行访问数据,因此即使没有索引,对于大数据量的访问,Hive 仍然可以体现出优势。数据库中,通常会针对一个或者几个列建立索引,因此对于少量的特定条件的数据的访问,数据库可以有很高的效率,较低的延迟。由于数据的访问延迟较高,决定了 Hive 不适合在线数据查询。
4、执行
Hive中大多数查询的执行是通过 Hadoop 提供的 MapReduce 来实现的。而数据库通常有自己的执行引擎。
5、数据规模
由于Hive建立在集群上并可以利用MapReduce进行并行计算,因此可以支持很大规模的数据;对应的,数据库可以支持的数据规模较小。
二、DDL基本操作指令
1、展示数据库
hive> show databases;
OK
default
Time taken: 0.014 seconds, Fetched: 1 row(s)
2、使用数据库
hive> use default;
OK
Time taken: 0.012 seconds
3、展示表
hive> show tables;
OK
student
Time taken: 0.124 seconds, Fetched: 1 row(s)
4、数据导入
hive> load data local inpath '/opt/module/datas/mfd_day_share_interest.txt' into table default.mfd_interest_data;
5、Hive查看HDFS目录文件
hive> dfs -lsr /;
lsr: DEPRECATED: Please use 'ls -R' instead.
drwxr-xr-x - 1 supergroup 0 2019-02-22 14:55 /user/hive/warehouse
drwxr-xr-x - 1 supergroup 0 2019-02-22 14:55 /user/hive/warehouse/mfd_interest_data
-rwxr-xr-x - 1 supergroup 9740 2019-02-22 14:55 /user/hive/warehouse/mfd_interest_data/mfd_day_share_interest.csv
drwxr-xr-x - 1 supergroup 0 2019-01-11 10:50 /user/hive/warehouse/student
也可以使用
hive> dfs -ls /;
查看根目录文件,不展示所有的文件
6、Hive查看本地目录文件
hive> ! ls /home;
1
在Hive控制台,使用!后可以直接使用本地命令的查看预览操作
7、查看Hive历史操作命令
[1@hadoop1 ~]$ cat .hivehistory
8、查看表的详细信息
hive> desc formatted mfd_interest_external;
OK
# col_name data_type comment
tdate bigint
interest double
year_interest double
# Detailed Table Information
Database: default
Owner: 1
CreateTime: Fri May 22 16:55:46 CST 2019
LastAccessTime: UNKNOWN
Protect Mode: None
Retention: 0
Location: hdfs://hadoop1:8020/user/hive/warehouse/mfd_interest_external
Table Type: EXTERNAL_TABLE
Table Parameters:
COLUMN_STATS_ACCURATE true
EXTERNAL TRUE
numFiles 1
totalSize 9740
transient_lastDdlTime 1550835770
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
field.delim ,
serialization.format ,
Time taken: 0.083 seconds, Fetched: 33 row(s)
9、创建表
<1>、创建.csv方法、创建.tsv是by"\t"
hive> create table mfd_interest_data(tdate bigint,interest_rate double,year_date double) row format delimited fields terminated by '\t';
OK
Time taken: 2.071 seconds
<2>、创建内部表
我们平时所创建的表,默认都是管理表,也就是内部表,因为这种表,Hive会或多或少的控制着数据的生命周期。Hive默认情况下会将这些数据存储存在由配置项hive.metastore.warehouse.dir所定义的目录的子目录之下。并且当我们删除这个表的时候,Hive也会删除这个表中的数据,管理表不适合和其他工具共享数据。
hive> create table if not exists student2 (id int,name string) row format delimited fields terminated by '\t' stored as textfile location '/user/hive/warehouse/student2';
OK
Time taken: 0.067 seconds
<3>、根据查询结果创建表
create table if not exists student3 as select id, name from student
<4>、根据已经存在的表创建表
create table if not exists student4 like student
<5>、创建外部表
因为表是外部表,所有Hive并非认为其完全拥有这份数据。删除该表并不会删除掉这份数据,不过描述表的元数据信息会被删除掉。
管理表和外部表的使用场景:每天将收集到的网站日志定期流入HDFS文本文件。在外部表(原始日志表)的基础上做大量的统计分析,用到的中间表、结果表使用内部表存储,数据通过SELECT+INSERT进入内部表。
create external table if not exists default.dept(deptno int,dname string,loc int) row format delimited fields terminated by '\t';
10、分区表
分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。
<1>、创建分区表并且导入数据
hive (default)> create table dept_partition(deptno int, dname string, loc string) partitioned by (month string) row format delimited fields terminated by '\t';
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201709');
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201708');
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201707');
<2>、对于多个分区表的联合查询操作(这样的对表操作会比单区表快很多,使用一个MapReduce案例就知道了)
hive (default)> select * from dept_partition where month='201707'
union
select * from dept_partition where month='201708'
union
select * from dept_partition where month='201709';
<3>、创建一个新的分区
hive (default)> alter table dept_partition add partition(month='201706') ;
<4>、同时创建多个分区(partition之间用空格隔开)
hive (default)> alter table dept_partition add partition(month='201705') partition(month='201704');
<5>、查询已经创建的分区
hive>show partitions dept_partition;
<6>、删除分区
1、删除单个分区
hive (default)> alter table dept_partition drop partition (month='201704');
2、同时删除多个分区
hive (default)> alter table dept_partition drop partition (month='201705'), partition (month='201706');
注意:和创建多个分区的语句不一样,创建多个分区partition之间用空格隔开,删除多个分区partition之间用逗号隔开
<7>、查看分区表结构
hive>desc formatted dept_partition;
<8>、创建二级分区表
hive (default)> create table dept_partition2(
deptno int, dname string, loc string
)
partitioned by (month string, day string)
row format delimited fields terminated by '\t';
11、将数据上传到HDFS
把数据直接上传到分区目录上,让分区表和数据产生关联的三种方式
<1>、上传数据后修复
在HDFS创建文件
hive (default)> dfs -mkdir -p /user/hive/warehouse/dept_partition2/month=201709/day=12;
hive (default)> dfs -put /opt/module/datas/dept.txt /user/hive/warehouse/dept_partition2/month=201709/day=12;
查询数据
hive (default)> select * from dept_partition2 where month='201709' and day='12'
发现查询不到刚才上传的数据,下面执行修复命令
hive>msck repair table dept_partition2;
再次执行查询命令就可以查看到数据了
<2>、上传数据后添加分区
上传数据
hive (default)> dfs -mkdir -p /user/hive/warehouse/dept_partition2/month=201709/day=11;
hive (default)> dfs -put /opt/module/datas/dept.txt /user/hive/warehouse/dept_partition2/month=201709/day=11;
执行添加分区
hive (default)> alter table dept_partition2 add partition(month='201709', day='11');
查询数据
hive (default)> select * from dept_partition2 where month='201709' and day='11';
<3>、上传数据后load数据到分区
创建目录
hive (default)> dfs -mkdir -p /user/hive/warehouse/dept_partition2/month=201709/day=10;
上传数据
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table dept_partition2 partition(month='201709',day='10');
查询数据
hive (default)> select * from dept_partition2 where month='201709' and day='10';
12、修改表
<1>、修改表名
hive (default)> alter table dept_partition2 rename to dept_partition3;
<2>、增加/修改/替换列信息
添加列
hive (default)> alter table dept_partition add columns(deptdesc string);
更新列
hive (default)> alter table dept_partition change column deptdesc desc int;
替换列
hive (default)> alter table dept_partition replace columns(deptno string, dname string, loc string);