1. Hive介绍
Hive是帮助搭建数据仓库的工具之一,它提供了类SQL语法,对HDFS里的数据进行读取,写入,管理,可以把存储在分布式存储系统中的数据映射成结构化的形式,提供了命令行工具或者JDBC驱动连接Hive进行使用。
2.Hive优缺点
优点:
(1) 提供了类SQL查询语法,最大限度的实现了和SQL标准的兼容
(2) 提供JDBC接口,开发人员更易开发应用
(3) 以MR作为默认的计算引擎,HDFS作为存储系统,为超大数据集提供计算/扩展能力
(4) 统一的元数据管理(Derby、Mysql等),并可与Pig、Spark等共享
元数据: Hive表对应的字段、属性还有表对应的存储的HDFS目录。
缺点:
(1) Hive的HQL表达能力有限,比如不支持update更新、非等值连接、delete,不建议用insert单条等;
不支持,归根结底还是Hadoop不支持对HDFS里的数据操作:
①update 对文件修改,②delete删除一条数据
③非等值连接 如两张表进行join,on后的字段关系只支持a.id=b.id,如果是不等关系,则无法翻译成mapreduce。
④insert单条 代表插入一条数据,可以使用但不建议使用。
如果执行insert插入一条数据,对应的Hive会在HDFS对应当前Hive表的目录下创建一个文件存放该条数据,如果再次insert单条,则会再在HDFS对应Hive表目录下再创建一个文件存放insert的单条数据,由此会产生很多小文件。
对于Hadoop来说,小文件不友好:
- 从存储方面:一个小文件会占用一个Block块,一个Block块会占用一条元数据信息,而元数据信息会存放到Namenode中,有可能一个小文件中的内容还没有一条元数据大,因此如果产生多个小文件,就会占用Namenode的内存。
- 从计算方面:一个小文件会对应一个MapTask,对应一个切片,之后申请一个环形缓冲区,环形缓冲区也会占用内存,其次,一个小文件会占用一个线程对它进行处理,浪费资源。
(2) Hive自动生成MapReduce作业,HQL调优困难。
MapReduce执行的时候会有个Shuffle流程,调优方法可以是增大缓冲区、调大Block块大小、增加Fetch拉取数据的线程数或者拉完后增大Reduce缓冲区的大小等等。但对于整个Shuffle流程,只要Job任务一执行,可管控的空间就很少,人为无非就是编写Map中的执行逻辑以及Reducer中的执行逻辑。Shuffle流程可控不多,就会造成HQL调优困难
(3) 粒度较粗,可控性差,因为Hive是在读取数据的时候进行类型转换,而Mysql是在数据写入的时候就进行了类型转换。
(4) Hive生成MapReduce作业,高延迟,不适合实时查询,适合做批处理。
MapReduce执行的时候底层走的是Shuffle流程,而Shuffle流程高度依赖于磁盘,因此比较慢,高延迟。(注: 如果想要写完SQL立马出结果,可以使用SparkSQL或者使用Impala,因为它的底层是基于内存进行计算的)
3.Hive和关系型数据库的区别
(1) Hive和关系型数据库存储文件的系统不同,Hive使用的是Hadoop的HDFS(Hadoop的分布式文件系统),关系型数据库则是服务器本地的文件系统(Mysql默认用的是InnoDB数据库引擎)
(2) Hive使用MapReduce做计算,与传统数据库相比计算数据规模要大得多
(3) 关系型数据库是为了实时查询的业务设计的,而Hive是为了海量数据做统计分析的,实时性差;实时性差导致Hive的应用场景和关系型数据库有很大区别。
mysql适用于OLTP联机事务处理
Hive适用于OLAP联机分析处理
(4) Hive很容易扩展自己的存储能力和计算能力,这个是继承Hadoop的,而关系型数据库的扩展性相对来说较差。
Hive | 关系型数据库 | |
查询语言 | HQL | SQL |
数据存储 | HDFS | 本地磁盘 |
执行 | MapReduce Spark | 数据库引擎 |
数据存储校验 | 存储不校验 | 存储校验 |
可扩展性 | 强 | 有限 |
执行延迟 | 高(MR) | 低 |
处理数据规模 | 大 | 小 |
涉及到传统数据库和数据仓库的区别:
从存储数据体量上,数据仓库存储的数据量更多,数据库相对少一些;
从存储数据类型上,一般的数据仓库可以存储结构化数据、半结构化数据(json格式、xml)、非结构化数据,而数据库一般只能存储结构化数据;
4.Hive架构
包括服务端组件和客户端组件
服务端组件:
Driver组件:包括Complier(编译),Optimizer(优化)和Executor(执行),其作用是将HiveQL(类SQL)语句进行解析、解析优化、生成执行计划,然后调用底层的MapReduce计算框架。
Metastore组件:元数据服务组件,使用该组件存取Hive的元数据,Hive的元数据存储在关系数据库里,Hive支持的关系数据库有Derby和Mysql。作用是:客户端连接metastor服务,metastore再连接mysql数据库来存取元数据。
Hiveserver2服务:用于进行可扩展且跨语言的服务开发,Hive集成了该服务,能让不同的编程语言调用Hive的接口,还可以做权限管理。
客户端组件:
CLI:命令行接口
JDBC/ODBC:Hive架构的JDBC和ODBC接口是建立在Hiveserver2客户端之上
WEBGUI:通过网页的方式访问Hive提供的服务,该接口对应Hive的HWI组件,使用前要启动HWI服务。
5.SQL的执行流程
通过Hive的客户端工具写一个SQL,将SQL发给Driver,Driver对sql进行编译,优化,执行。首先Driver把sql发送到编译器Compiler,编译器连接metastore元数据服务,获取user表对应的元数据信息,此时编译器就会生成执行计划,然后将执行计划发送给Driver,Driver再交给执行引擎,默认的MapReduce。当sql语句如 select * from user;,select * 是不需要走MR的,只要知道user表在HDFS哪里就可以从这个目录下把这个文件cat出来,就相当于做了Hadoop的读流程,会去访问NameNode,NameNode会返回给执行引擎user表对应的文件块的信息,hive作为客户端就会把文件信息读取出来;当sql语句如select age,count(*) from user group by age;,就需要走MR,需要将执行计划提交给ResourceManager,就相当于走了Yarn的Job的提交流程,即当向Yarn上提交一个任务的时候,首先会创建一个ApplicationMaster用于管理这个任务,再进行任务的初始化,发现有多少个MapTask,有多少个ReduceTask,然后分别在NodeManager上进行启动,并且监控,运行完后ApplicationMaster就结束了,将结果进行返回,最后返回到客户端,打印到屏幕上。
Hive将SQL转化为MapReduce任务的整个编译过程大概:
- Antlr定义语法规则,完成SQL语法解析,将SQL转化为抽象语法树AST Tree
- 遍历AST Tree,抽象出查询的基本组成单元QueryBlock
- 遍历QueryBlock,翻译为执行操作树OperatorTree
- 逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少Shuffle数据量
- 遍历OperatorTree,翻译为Mapreduce任务
- 物理层优化器进行MapReduce任务的变换,生成最终的执行计划
练习:
create table dept(
deptid int,
deptname string,
address string);
insert into dept values
(1,'研发部','北京'),
(2,'人事部','上海'),
(3,'销售部','深圳'),
(4,'公关部','东莞');
create table emp(
empid int,
empname string,
salary DECIMAL,
ruzhidate date,
mgr int,
deptid int);
insert into emp values
(1001, 'tom', 18000, '2013-10-11', 1005, 1),
(1002, 'jerry', 13000, '2021-11-11', 1005, 1),
(1003, 'jack', 10000, '2020-09-11', 1001, 1),
(1004, 'rose', 5000, '2020-10-11', 1001, 2),
(1005, 'bob', 20000, '2018-08-11', null, 2)
--或者
vi dept
load data local inpath '/home/hadoop/dept' into table dept;
select * from dept;
vi emp
load data local inpath '/home/hadoop/emp' into table emp;
select * from emp;
--1.统计全公司工资最高的三个人,排序的使用、limit
--可以用sort by同时设置了reduce数量为1,等价于order by
select * from emp order by salary desc limit 3;
--2.查出部门的员工数和部门的名称,join和group by的用法
select d.deptname,count(*) from dept d join emp e on d.deptid = e.deptid group by d.deptname;
--3.统计最高的工资是多少,以及这个人是谁,join和子查询的用法
select empname,salary from emp order by salary desc limit 1;
--或者
select e.empname,e.salary from emp e
join (select max(salary) as maxsalary from emp) t1
on e.salary=t1.maxsalary;
select empname,salary from emp where salary = (select max(salary) from emp);
--在hive低版本中不支持单个值用=查询(无论子查询中几个值都只支持in),高版本做了优化,即=后面使用子查询,如果子查询中只有一个值,则可以使用=,如果子查询中是多个值,则需要将=换成in。
可真是慢。