Hive是如何让MapReduce实现SQL操作的

前面我们说过MapReduce的运算流程,整体架构方法,JobTracker与TaskTracker之间的通信协调关系等等。虽然知道我们只需要自己完成Map和Reduce就可以实现MapReduce的运算,但是还有很多人习惯使用SQL进行数据分析,MapReduce编程不是那么容易,因此就有了Hive的存在。

首先看看如何用MapReduce实现SQL数据分析。

MapReduce实现SQL的原理

先看一个简单的SQL语句:

	SELECT pageid, age, count(1) FROM pv_users GROUP BY pageid, age;

先来看看MapReduce实现SQL的原理。

具体数据输入和执行结果请看下图:
Hive是如何让MapReduce实现SQL操作的_第1张图片
左边是要分析的表,右边是分析结果。实际上把左边表相同的行进行累计求和,就能得到右边的表,看起来和WordCount计算很类似,确实也是这样。

来看看这条SQL语句的MapReduce的计算过程:

  1. 首先是Map的计算,先整理成map的形式,也就是<1,25>,<2,25>此类的,然后与count值进行结合成一个新的map,也就是<<2,25>,1>这样。
  2. map的输出经过shuffle之后,相同的key value组合到一起,也就是<<2,25>,<1,1>>,<1,1>代表的是Value记录
  3. 到了reduce阶段,进行聚合,也就是<<2,25>,2>

如下图:
Hive是如何让MapReduce实现SQL操作的_第2张图片
在数据仓库中SQL是最常用的分析工具,既然一条SQL可以通过MapReduce程序实现,那么Hive也可以。
现在来看看一下Hive架构。

Hive的架构

Hive能够直接处理输入的SQL语句,调用MapReduce计算框架完成数据分析操作。来看看架构图:
Hive是如何让MapReduce实现SQL操作的_第3张图片
通过Hive的Client向Hive提交SQL命令。

如果是创建数据表的DDL语句。Hive就会通过执行引擎Driver将数据表的信息记录在Metastore元数据组件中,这个组件通常用一个关系数据库实现,记录表名、字段名、字段类型、关联HDFS文件路径等这些数据库的Meta信息。

如果提交的是查询分析数据的DQL语句,Driver就会将该语句提交给自己的编译器Compiler进行语法分析、语法解析、语法优化等一系列操作,最后生成一个MapReduce执行计划,然后根据执行计划生成一个MapReduce的作业,提交给Hadoop MapReduce计算框架处理。

对于一个较简单的SQL命令,比如:

		SELECT * FROM status_updates WHERE status LIKE ‘michael jackson’;

对应的Hive执行计划如下图:
Hive是如何让MapReduce实现SQL操作的_第4张图片
Hive内部预置了很多函数,Hive的执行计划就是根据SQL语句生成这些函数的DAG(有向无环图),然后封装进MapReduce的map和reduce函数中。这个例子中,map函数调用了三个Hive内置函数:TableScanOperator、FilterOperator、FileOutputOperator,就完成了map计算,而且无需reduce函数。

Hive如何实现join操作

除了上面这些简单的聚合过滤操作,Hive还能执行连接(join on)操作。

		SELECT pageid , age,count(1) from pv_users group by pageid,age;

这是文章开头的SQL语句,pv_users表的数据在实际中是无法直接得到的,因为pageid数据来自用户访问日志,每个用户进行一次页面浏览,就会生成一条访问记录,保存在page_view表中。而age年龄信息则记录在用户表user中。pv_user表是和另一张表关联的,我们select的数据也来自不同的表,那么就需要join操作了,先看我所说的两张表:
Hive是如何让MapReduce实现SQL操作的_第5张图片
假设是靠userid关联的,然后来重新表达一下新的SQL语句。

select pv.pageid,u.age 
from page_view pv 
join user u on (pv.userid = u.userid);

同样,这个SQL命令也可以转化为MapReduce计算,连接的过程如下图所示:
Hive是如何让MapReduce实现SQL操作的_第6张图片
从图上看,join的MapReduce计算过程和前面的group by稍有不同,因为join涉及到两张表,来自两个文件,所以需要在map输出的时候进行标记,比如来自第一张表的输出Value就标记为<1,X>,1表示数据来自第一张表。

然后会进行shuffle,相同的key被输入到同一个reduce函数进行聚合,根据表的标记对value数据求笛卡尔积,用第一张表的每条记录和第二张表的每条记录连接,输出就是join的结果。

Hive的源码中join的时间复杂度O(n²),对来自两张表的记录进行连接操作。

总结

随着大数据SQL的应用市场多样化之后更多的大数据SQL引擎也很火。

Cloudera开发了Impala,这是一种运行在HDFS上的MPP架构的SQL引擎。和MapReduce启动Map和Reduce两种执行过程,将计算分成两个阶段进行计算不同,Impala在所有DataNode服务器上部署相同的Impalad进程,多个Impalad进程相互协作,共同完成SQL计算,在一些统计场景中,Impala可以做到毫秒级的计算速度。

后来SparkSql出现了,引擎是基于Spark的,由于速度很快,快于Hive,所以后来Hive也兼容了Spark,可以在Spark上计算Hive的执行计划。总的来说这么多集群,做到技术嫁接,还是很有创新性的。

你可能感兴趣的:(大数据开发)