目录

HIVE的基本理解,使用,特性

什么是hive

hive元数据

hive默认分隔符   \001

hive行级更新操作的前提条件

hive/mysql/hbase比较

函数

hive解决wordcount案例

hive内部表与外部表

hql特性:

hive常用命令:

读取数据文件方法:

查看yarn mr日志

HIVE动态分区

HIVE锁表问题

HIVE数据倾斜

HIVE优化

hive 小表与大表关联

大表和小表join

执行MR或聚集查询卡死

4个By问题:

描述数据中的null,在hive底层如何存储?

Hive中 split、coalesce以及collect_list函数的用法?

hive有哪些保存元数据的模式,有什么特点

hive 相对于 Oracle 来说有那些优点?

Hive经典HQL题目

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

Hive SQL 的编译过程



HIVE的基本理解,使用,特性


什么是hive

hive------mapreduce的封装,意义在于将sql语言转化为mapreduce的过程,本质是个mapreduce,批处理强大,不支持单条纪录级别的update操作,随机读写性能差    (hive是个计算框架,不能存储数据)

hbase-----hdfs的包装,本质是数据存储,克服hdfs在随机读写上的缺点

kudu-----不及HDFS批处理快,也不及HBase随机读写能力强,但是反过来它比HBase批处理快(适用于OLAP的分析场景),而且比HDFS随机读写能力强,适用于实时写入或者更新的场景。

hive的表本质就是hadoop的目录/文件(文件夹),hive依托hdfs存储,依托yarn资源调度,依托mapreduce进行计算

hive元数据

hive元数据默认存储在derby中,也可存储与mysql中,元数据是指表的信息,比如表的名字,表有哪些列等等描述信息。我们向表中插入的数据是保存在HDFS上的。

hive默认分隔符   \001

hive行级更新操作的前提条件

1 注意存储格式按ORC方式
2 进行数据分桶
3 添加表属性:"transactional"="true"   该设置不可逆,使得该表
4.hive-site.xml里要做相关配置  参见 https://blog.csdn.net/wzy0623/article/details/51483674

hive/mysql/hbase比较

hive mysql hbase
数据量
速度 数据量大时快 数据量小时快
查询 增删改 增删改

函数

系统函数: 月: date_format     last_day                   周:    next_day                                            日:date_add date_sub  date_diff              解析json: get_json_object

开窗函数:详见https://blog.csdn.net/wangpei1949/article/details/81437574

排序开窗函数、聚合开窗函数、first_vlaue、last_value、lag(往上)、lead(往下)、

ntile(分组再分组)、cume_dist(小于等于当前值x的行数百分比)、percent_rank(计算超过了百分之多少的人(当前行的rank值-1)/(分组内的总行数-1))

排序开窗:

rank() over()                            1,1,3,4,5,6,7              跳跃排序

row_number() over()               1,2,3,4,5,6,7

dense_rank() over()                1,1,2,3,4,5,6               连续排序(最大排名会小于总数)

pecent_rank函数:

-- percent_rank 开窗函数
计算给定行的百分比排名。可以用来计算超过了百分之多少的人。如360小助手开机速度超过了百分之多少的人。
(当前行的rank值-1)/(分组内的总行数-1)select studentid,departmentid,classid,math,
row_number() over(partition by departmentid,classid order by math) as row_number,
percent_rank() over(partition by departmentid,classid order by math) as percent_rank
from student_scores;结果
studentid   departmentid    classid math    row_number  percent_rank
111         department1     class1  69      1           0.0
113         department1     class1  74      2           0.25
112         department1     class1  80      3           0.5
115         department1     class1  93      4           0.75
114         department1     class1  94      5           1.0
124         department1     class2  70      1           0.0
121         department1     class2  74      2           0.3333333333333333
123         department1     class2  78      3           0.6666666666666666
122         department1     class2  86      4           1.0
216         department2     class1  74      1           0.0
215         department2     class1  82      2           0.2
212         department2     class1  83      3           0.4
211         department2     class1  93      4           0.6
213         department2     class1  94      5           0.8
214         department2     class1  94      6           0.8
223         department2     class2  74      1           0.0
222         department2     class2  78      2           0.25
224         department2     class2  80      3           0.5
225         department2     class2  85      4           0.75
221         department2     class2  99      5           1.0结果解释:studentid=115,percent_rank=(4-1)/(5-1)=0.75studentid=123,percent_rank=(3-1)/(4-1)=0.6666666666666666

聚合开窗:sum() over()、count() over()、min() over()、max() over()、avg() over()、

以按classId分组、按math排序后、按当前行+往前1行+往后2行的行作为窗口:

select count(math) over(partition by classId order by math rows between 1 preceding and 2 following) as last_value4
from student_scores where departmentId='department1';

first_value() over()、last_value() over()

lag开窗函数:lag(col,n,default) 用于统计窗口内往上第n个值。
    col:列名
    n:往上第n行
    default:往上第n行为NULL时候,取默认值,不指定则取NULL

lead开窗函数:lead(col,n,default) 用于统计窗口内往下第n个值。
    col:列名
    n:往下第n行
    default:往下第n行为NULL时候,取默认值,不指定则取NULL

cume_dist开窗函数

-- cume_dist 开窗函数
计算某个窗口或分区中某个值的累积分布。假定升序排序,则使用以下公式确定累积分布:
小于等于当前值x的行数 / 窗口或partition分区内的总行数。其中,x 等于 order by 子句中指定的列的当前行中的值。select studentId,math,departmentId,classId,
-- 统计小于等于当前分数的人数占总人数的比例
cume_dist() over(order by math) as cume_dist1,
-- 统计大于等于当前分数的人数占总人数的比例
cume_dist() over(order by math desc) as cume_dist2,
-- 统计分区内小于等于当前分数的人数占总人数的比例
cume_dist() over(partition by classId order by math) as cume_dist3
from student_scores where departmentId='department1';结果
studentid   math    departmentid    classid cume_dist1              cume_dist2          cume_dist3
111         69      department1     class1  0.1111111111111111      1.0                 0.2
113         74      department1     class1  0.4444444444444444      0.7777777777777778  0.4
112         80      department1     class1  0.6666666666666666      0.4444444444444444  0.6
115         93      department1     class1  0.8888888888888888      0.2222222222222222  0.8
114         94      department1     class1  1.0                     0.1111111111111111  1.0
124         70      department1     class2  0.2222222222222222      0.8888888888888888  0.25
121         74      department1     class2  0.4444444444444444      0.7777777777777778  0.5
123         78      department1     class2  0.5555555555555556      0.5555555555555556  0.75
122         86      department1     class2  0.7777777777777778      0.3333333333333333  1.0结果解释:第三行:cume_dist1=小于等于80的人数为6/总人数9=0.6666666666666666cume_dist2=大于等于80的人数为4/总人数9=0.4444444444444444cume_dist3=分区内小于等于80的人数为3/分区内总人数5=0.6

ntile开窗函数:

-- ntile 开窗函数
将分区中已排序的行划分为大小尽可能相等的指定数量的排名的组,并返回给定行所在的组的排名。select *,
-- 对分区内的数据分成两组
ntile(2) over(partition by departmentid order by math) as ntile1,
-- 对分区内的数据分成三组
ntile(3) over(partition by departmentid order by math) as ntile2
from student_scores;结果
id  studentid   language    math    english classid departmentid    ntile1  ntile2
1   111         68          69      90      class1  department1     1       1
9   124         76          70      76      class2  department1     1       1
6   121         96          74      79      class2  department1     1       1
3   113         90          74      75      class1  department1     1       2
8   123         70          78      61      class2  department1     1       2
2   112         73          80      96      class1  department1     2       2
7   122         89          86      85      class2  department1     2       3
5   115         99          93      89      class1  department1     2       3
4   114         89          94      93      class1  department1     2       3
18  223         79          74      96      class2  department2     1       1
15  216         85          74      93      class1  department2     1       1
17  222         80          78      96      class2  department2     1       1
19  224         75          80      78      class2  department2     1       1
14  215         84          82      73      class1  department2     1       2
11  212         76          83      75      class1  department2     1       2
20  225         82          85      63      class2  department2     2       2
10  211         89          93      60      class1  department2     2       2
12  213         71          94      90      class1  department2     2       3
13  214         94          94      66      class1  department2     2       3
16  221         77          99      61      class2  department2     2       3结果解释:第8行ntile1:对分区的数据均匀分成2组后,当前行的组排名为2ntile2:对分区的数据均匀分成3组后,当前行的组排名为3

hive解决wordcount案例

select word,count(*) from (
select explode(split(sentence.' ')) word from article
) t
group by word 

hive内部表与外部表

create table                   create external table
内部表               vs            外部表
表结构和数据均丢失     表结构丢失,但数据仍在           
不可挽回                       把表重建,数据自动恢复

hql特性:

1.0.13版本前的hive仅支持from 后面的子查询,0.13版本后的hive新增支持 in(not in)后面的子查询/ EXISTS(NOT EXISTS)后面的子查询

2. 子查询相当于表名,必须有别名。

3. hive 不支持union ,只支持union all 

4. 子查询中使用union all 时,在子查询里不能使用count、sum 等 聚合函数

5. 两表直接进行union all 可以使用count、sum 等聚合函数

6. 两张表进行union all 取相同的字段名称,可正常输出指定数据内容,且结果为两张表的结果集

hive常用命令:

普通创建:

-- 创建表,external 外部表
CREATE external TABLE IF NOT EXISTS t2(id int,name string,age int)
COMMENT 'xx' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' STORED AS TEXTFILE ;
-- 加载数据到hive表
load data local inpath '/home/centos/customers.txt' into table t2 ;   -- local上传文件
load data inpath '/user/centos/customers.txt' [overwrite] into table t2 ; -- 移动文件
-- 加载数据到分区表
load data local inpath '/home/centos/customers.txt' into table t3 partition(year=2014,month=11);
-- 启用/禁用表
ALTER TABLE t2 ENABLE NO_DROP;  -- 不允许删除
ALTER TABLE t2 DISABLE NO_DROP; -- 允许删除
-- 复制表
create table tt as select * from users ;        -- 携带数据和表结构
create table tt like users ;            -- 不带数据,只有表结构

分区表:

-- 创建分区表.
create table t3(id int,name string,age int) partition by (year int,month int) row farmat delimited fields terminated by ','  stored as textfile;
-- 显式表的分区信息
show partitions t3;
-- 添加分区,创建目录
alter table add partition (year = 2021,month = 03)
-- 删除分区
alter table t3 drop if exists partition (year = 2021,month = 03)
-- 分区结构
/user/hive/warehouse/mydb2.db/t3/year=2014/month=11
/user/hive/warehouse/mydb2.db/t3/year=2014/month=12
-- 加载数据到分区表
load data [local] inpath '/home/centos/customers.txt' [overwrite] into table t3 [partition (year 2021,month 03)]

分桶表:

分库分表的时候就会分桶

-- 创建桶表t4
create table t4 (id int,name string,age int) clusted by (id) into 3 buckets row farmat delimited fields terminated by ','  stored as textfile;
-- 加载数据不会进行分桶操作
load data [local] inpath '/home/centos/customers.txt' into table t4;
-- 查询t3表数据插入到t4中。
insert into t4 select id,name,age from t3;

桶表的数量如何设置?
评估数据量,保证每个桶的数据量block的2倍大小。(从2.7.3版本开始,官方关于Data Blocks 的说明中,block size由64 MB变成了128 MB的。)

既分区又分桶:

create table t_test (id int)
partitioned by (type string)
clustered by (id) into 3 buckets
row format delimited fields terminated by '\t';
-- partition by 要写在clustered by 前面

hive删除数据: 

hive删除数据不支持单条纪录级别

--------------------------------------- 分区表
----------------删除具体partition
alter table t4 drop if exists partition (year = 2021,month = 02);
----------------删除partition内部分数据
insert overwrite into table t4 partition (year = 2021,month = 02)
select * from t4 where year = 2021 and month = 02 and age<20;--------------------------------------- 非分区表
INSERT OVERWRITE TABLE t4 SELECT * FROM t4 WHERE age is not null;

读取数据文件方法:

TextFile , SequenceFile(二进制) , RCFile
SequenceFile(二进制): 是hadoop提供的一种二进制文件,<key,value>形式序列化到文件中.java Writable接口进行序列化和反序列化
RCFile: 是hive专门推出的面向列的数据格式

查看yarn mr日志

查看application的日志:[hadoop@hadoop01 ~]$ yarn logs -applicationId application_1523430872525_0002 查看具体某一个container的日志:[hadoop@hadoop01 ~]$ yarn logs -applicationId application_1523430872525_0002 -containerId container_1523191604137_0016_02_000001 -nodeAddress hadoop01:60127

HIVE动态分区


用的是动态分区吗?动态分区的底层原理是什么?

a. 静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。

b. 详细来说,静态分区的列实在编译时期,通过用户传递来决定的;动态分区只有在 SQL 执行时才能决定。

c. 动态分区是基于查询参数的位置去推断分区的名称,从而建立分区

hive单字段动态分区:(默认最后一个字段对应分区字段)

hive>create table dpartition(id int ,name string )partitioned by(ct string  );
hive>hive.exec.dynamici.partition=true;  #开启动态分区,默认是falseset hive.exec.dynamic.partition.mode=nonstrict; #开启允许所有分区都是动态的,否则必须要有静态分区才能使用。insert overwrite table dpartitionpartition(ct)select id ,name,city from  mytest_tmp2_p; 要点:因为dpartition表中只有两个字段,所以当我们查询了三个字段时(多了city字段),所以系统默认以最后一个字段city为分区名,因为分区表的分区字段默认也是该表中的字段,且依次排在表中字段的最后面。
hive>--查看可知,hive已经完成了以city字段为分区字段,实现了动态分区。
hive (fdm_sor)> show partitions dpartition;
partition
ct=beijing
ct=beijing1

hive多字段半自动分区:(静态分区要放在动态分区前面,分区字段顺序和partition 字段顺序一致)

1.创建一个只有一个字段,两个分区字段的分区表
hive (fdm_sor)> create table ds_parttion(id int ) > partitioned by (state string ,ct string );
2.往该分区表半动态分区插入数据
hive>set hive.exec.dynamici.partition=true;set hive.exec.dynamic.partition.mode=nonstrict;insert overwrite table ds_parttionpartition(state='china',ct)  #state分区为静态,ct为动态分区,以查询的city字段为分区名select id ,city from  mytest_tmp2_p; 

hive多字段全部动态分区:(注意顺序)

 set hive.exec.dynamici.partition=true;set hive.exec.dynamic.partition.mode=nonstrict;insert overwrite table ds_parttionpartition(state,ct)select id ,country,city from  mytest_tmp2_p;
注意:字段的个数和顺序不能弄错。

动态参数必备参数:

  • hive.exec.dynamic.partition                             开启动态分区,默认不开
  • hive.exec.dynamic.partition.mode                  动态分区的模式:默认strict,要求必须要有个静态分区字段;一般需设置为nonstrict表示所有分区字段可使用动态分区
  • hive.exec.max.dynamic.partitions.pernode   每个执行MR的节点上最大能创建的分区数(比如一年365天,分区数要设置>365)
  • hive.exec.max.dynamic.partitions                  所有MR节点上最大能创建的分区数
  • hive.exec.max.created.files                             整个MR JOB中最大能创建的hdfs文件数

Hive的静态分区,实际上就是手动指定分区的值为静态值,适用于小批量数据

HIVE锁表问题


hive有两种锁,一种是 共享锁(SHARED),查询时会有。SHARED(共享锁 S)和 Exclusive(排他锁 X)。只有都是共享锁才不会锁表/分区。

解决方法:

1.先查看有没有锁。表级查看和分区级查看。

//   1 查询是否锁表:hive> show locks ;
//   2 发现表:test 被锁
//   3 临时解决办法
hive> unlock table test;   //亲测这个命令基本没啥用,表依然处于无法操作状态,但是可以试试
hive> unlock table test partition(dt='2019-05-05'); //解锁分区锁命令可以用这个SHOW LOCKS <TABLE_NAME>;
SHOW LOCKS <TABLE_NAME> EXTENDED;
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>);
SHOW LOCKS <TABLE_NAME> PARTITION (<PARTITION_DESC>) EXTENDED;

2.调整sql语句或者插入数据操作之间设置sleep或者设置相关关于hive锁冲突时重新等待锁释放的参数

3.关闭锁机制,set hive.support.concurrency=false

4.表建立分区,这样锁就会到分区级别,就会降低锁表粒度。动态分区如非必要就关闭动态分区,因为动态分区的话,锁级别就到表,不到分区。 set hive.exec.dynamic.partition=false

5.关闭事务:set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DummyTxnManager

HIVE数据倾斜


阐述数据倾斜的原因:

数据分布不均匀;不同数据类型进行关联操作(只会有一个reduce);空数值易造成

解决数据倾斜的方法:

1.mapjoin     在map端做join操作减少数据,减少到reduce端汇总的数据

2.如果是不同数据类型关联造成的就在sql中转成一致的数据类型再关联

3. group by操作

注:group by 优于distinct group

解决方式:采用sum() group by的方式来替换count(distinct)完成计算。

4.开启数据倾斜时的负载均衡  set hive.groupby.skewindata=true

就是到reduce那后对于大的reduce再进行reduce       2个MRJOB

5.控制空值分布

将为空的key转变为字符串加纯随机数,将因空值而造成倾斜的数据分布到多个reducer  (本质和开启数据倾斜时的负载均衡是一样的)

将为空的key转变为字符串加随机数或纯随机数,将因空值而造成倾斜的数据分不到多个Reducer。
注:对于异常值如果不需要的话,最好是提前在where条件里过滤掉,这样可以使计算量大大减少。
实践中,可以使用case when对空值赋上随机值。此方法比直接写is not null更好,因为前者job数为1,后者为2.
使用case when实例1:
select userid, name from user_info a
join (
select case when userid is null  then  cast (rand(47)* 100000 as int )
else userid end from user_read_log
) b  on a.userid = b.userid
使用case when实例2:
select  '${date}' as thedate,a.search_type,a.query,a.category,a.cat_name,a.brand_id,a.brand_name,a.dir_type,a.rewcatid,a.new_cat_name,a.new_brand_id,f.brand_name as new_brand_name,a.pv,a.uv,a.ipv,a.ipvuv,a.trans_amt,a.trans_num,a.alipay_uv
from fdi_search_query_cat_qp_temp a
left outer join brand f
on  f.pt='${date}000000' and case when a.new_brand_id is null then concat('hive',rand() ) else a.new_brand_id end = f.brand_id;
如果上述的方法还不能解决,比如当有多个JOIN的时候,建议建立临时表,然后拆分HIVE SQL语句。

HIVE优化


 1. mapjoin默认打开

set hive.auto.convert.join = true;  --是否开自动mapjoin

set hive.mapjoin.smalltable.filesize;   --mapjoin的表size大小

以上两个参数同时使用,在hive.auto.convert.join为true时,只要小表size小于hive.mapjoin.smalltable.filesize的设置值,并且小表不是关联操作的最后一张表,小表就会走mapjoin。

MAPJION会把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join操作,省去了reduce运行的效率也会高很多。

set hive.auto.convert.join = true;set hive.mapjoin.smalltable.filesize = 6250000;select * from table_1 --小表,size  5mjoin table_2on 1=1;

mapjoin还有一个很大的好处是能够进行不等连接的join操作,如果将不等条件写在where中,那么mapreduce过程中会进行笛卡尔积,运行效率特别低,如果使用mapjoin操作,在map的过程中就完成了不等值的join操作,效率会高很多。

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。

mapjoin适用的场景:   关联操作中有一张表非常小;不等值的链接操作

2.行列过滤,就是在join操作前先进行where操作,减少数据集。

列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。

行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。

3.做好分区。(分桶用于采样)

4.小文件合并

CombineHiveInputformat      减少切片,进而减少Maptask,减少内存

打开merge功能 ==========>   如果是maponly 任务,merge功能默认打开;如果是mapreduce任务,需要打开merge功能

merge功能就是   执行完任务后,自动将小于16M的文件,合并到256M (hive块的大小)

5.合理设置map个数和reduce个数

6.启用压缩

采用快的,Map前的输入数据用可分片的LZO/Bzip2,Map和reduce之间的用快的,LZO/Snappy

好处:减少磁盘空间,减少网络传输      坏处:增加了解压缩的计算

7.采用列式存储orc,parquet                                提高查询效率;提高压缩比例

8.在map端开启 combiner            set hive.map.aggr = true

9.开启JVM重用(减少开关时间)

10.文章“Haoop总结”里的Mapreduce优化和Hadoop优化

hive 小表与大表关联

关于小表join大表的补充:
表join时的操作是这样的:一般是驱动表和另一张表,另一张表最好是小表,将另一张表加载入内存。在驱动表里每行匹配的时候,全表扫描小表。

a left outer join b        a是驱动表,b应是小表

a right outer join b      b是驱动表,a应是小表

大表和小表join

Map side join。将小表存入内存中,将小表复制多份,让每个map task内存中保留1份(如存放到hash table中),这样只需要
扫描小表。对于小表中的每一条记录key/value,在hash table中查找是否有相同的key,如果有,则连接后输出即可。

执行MR或聚集查询卡死


yarn节点分配给nodemanager运行资源的内存不够,就易出现执行MR卡死的状况,

调整参数 yar.nodemanager.resource.memory-mb  (集群中某个计算节点分配给nodemanager的最大可用内存,这个最大可用内存不是该节点最大内存,而是该节点最大内存划分出来的给nodemanager使用的内存)

增大NodeManager的默认内存,单个任务的默认内存,map任务的默认内存,reduce任务的默认内存。

4个By问题:


1)Sort By:分区内有序;  参见详解Sort by http://blog.itpub.net/26613085/viewspace-1130845/

hive> insert overwrite local directory ‘/home/hjl/sunwg/qqq’ select * from test09 sort by id;比较能看得出来,会输出reduce任务数个的文件,每个文件里都是根据Id排好序的。

2)Order By:全局排序,只有一个Reducer;

3)Distrbute By:类似MR中Partition,进行分区,结合sort by使用。

4) Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。

order by和sort by都可以实现排序的功能,不过具体怎么使用还得根据情况,如果数据量不是太大的情况可以使用order by,如果数据库过于庞大,最好还是使用sort by。

描述数据中的null,在hive底层如何存储?

null在hive底层默认是以"\N"来存储的,所以在sqoop到mysql之前需要将为null的数据替换成其他字符,否则sqoop提示错误

Hive中 split、coalesce以及collect_list函数的用法?

1. split将字符串转化为数组
2. coalesce(T v1,T v2,...) 返回参数中的第1个非空值;如果所有值都为null,那么返回null
3. collect_list列出该字段所有的值,不去重 select collect_list(id) from table;

hive有哪些保存元数据的模式,有什么特点

1)Single User Mode:
默认安装hive,hive是默认使用derby内存数据库保存hive的元数据,这样是不可以并发调用hive的,这种模式是hive默认的存储模式。
2)Multi User Mode:
通过网络连接到一个数据库中,是最经常使用到的模式。假设使用本机mysql服务器存储元数据。这种存储模式需要
在本地运行一个mysql服务器,并作如下配置(需要将mysql的jar包拷贝到$HIVE_HOME/lib目录下)。
3)Remote Server Mode:
在服务器端启动一个 MetaStoreServer,客户端利用 Thrift 协议通过 MetaStoreServer 访问元数据库。

hive 相对于 Oracle 来说有那些优点?

1)存储,hive 存储在 hdfs 上,oracle 存储在本地文件系统。
2)扩展性,hive 可以扩展到数千节点,oracle 理论上只可扩展到 100 台左右。
3)单表存储,数据量大 hive 可以分区分桶,oracle 数据量大只能分表。

Hive经典HQL题目

待总结

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

细致篇:https://blog.csdn.net/qq_41936805/article/details/97759502

简单篇:https://blog.csdn.net/wpwbb510582246/article/details/104759956?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-15.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-15.control

大神篇:https://tech.meituan.com/2014/02/12/hive-sql-to-mapreduce.html

大概总结:主要分为 select  ,group  by ,join ,count(distinct A) 单字段 ,count(distinct A),count(distinct B) 多字段。

  • select 主要就是map。

  • group by 涉及数据的重洗  整个过程是完整的MapReduce ,split,map,partition,(combine),shuffle(sort,merge,sort),reduce。
select pageid , age,count(1) from pv_users group by pageid,age;

  • Join涉及到多个表,所以开启多个MAP任务来抽取对应表的数据并打上所属表的标记来区分,shuffle后reduce任务根据标记来进行笛卡尔积,连接数据,输出数据。
select pv.pageid,u.age
from page_view pv
join user u on (pv.userid = u.userid);

  • Distinct 单个实现原理
select dealid, count(distinct uid) num from order group by dealid;

在进入reduce前,把它当 select dealid, uid ,count(1) as num from order group by dealid;来做。进入reduce后,key为dealid,进行汇聚。

  • Distinct 多个字段实现
select dealid, count(distinct uid), count(distinct date) from order group by dealid;

对所有的distinct字段编号,每行数据生成n行数据,那么相同字段就会分别排序,这时只需要在reduce阶段记录LastKey即可去重。Join操作是对不同表标记后进行笛卡尔积连接,这里是标记后分类累计排序。

Hive SQL 的编译过程

了解了MapReduce实现SQL基本操作之后,我们来看看Hive是如何将SQL转化为MapReduce任务的,整个编译过程分为六个阶段:

  1. Antlr定义SQL的语法规则,完成SQL词法,语法解析,将SQL转化为抽象语法树AST Tree
  2. 遍历AST Tree,抽象出查询的基本组成单元QueryBlock
  3. 遍历QueryBlock,翻译为执行操作树OperatorTree
  4. 逻辑层优化器进行OperatorTree变换,合并不必要的ReduceSinkOperator,减少shuffle数据量
  5. 遍历OperatorTree,翻译为MapReduce任务
  6. 物理层优化器进行MapReduce任务的变换,生成最终的执行计划

(有点复杂,待后续仔细研究,参见 https://tech.meituan.com/2014/02/12/hive-sql-to-mapreduce.html)

hive的进一步理解相关推荐

  1. Memcpy, blockcopy的进一步理解

    Memcpy, blockcopy的进一步理解 using System; using System.Runtime.InteropServices; using System.IO; namespa ...

  2. Java工作笔记-对反射的进一步理解

    目录 基本概念 代码与实例 基本概念 反射的进一步理解: 将类的各个组成部分封装为其他对象(将一个类的组成部分封装为其他对象) 就是反射. Java代码经历的三个阶段: 1. 写好代码.java后使用 ...

  3. 进一步理解CSS浮动与清除浮动

    本文主要探讨两个问题: 为什么CSS设置浮动会引起父元素塌陷 为什么设置clear:both能清除浮动,并撑开父元素. 起因 CSS的浮动,算是我在写网页时用的最多的属性之一.但要说我对浮动的了解程度 ...

  4. 规模因子和价值因子—进一步理解系统性风险

    上世纪二十年代的美国,当时的美国股市是一个高度散户化的市场,很多人就从交易中总结了市场规律,许多形形色色的规律都是昙花一现,唯独有两个策略经久不衰. 其中一个规律是买入市净率低的股票,"市净 ...

  5. 【MyBatis】进一步理解choose、when、otherwise标签

    choose.when.otherwise choose里面包含when.otherwise两个标签,choose是父标签,when和otherwise必须都要写在它里面 当 when 中有条件满足的 ...

  6. Magic Powder - 1 CodeForces - 670D1(优先队列进一步理解)

    写这个题的时候一直在想怎么才能动态排序(一遍改变数值,一遍从新改变相应的顺序),到最后才突然想起来这不就是优先队列吗,通过这题对优先队列的动态排序有了进一步理解.好题! AC代码: #include ...

  7. OpenGL学习笔记(八):进一步理解VAO、VBO和SHADER,并使用VAO、VBO和SHADER绘制一个三角形

    原博主博客地址:http://blog.csdn.net/qq21497936 本文章博客地址:http://blog.csdn.net/qq21497936/article/details/7888 ...

  8. (二)音视频:MediaCodec编码桌面信息 完整Demo 进一步理解H264

    (一)音视频:解码H264文件流程 渲染和拿到解码后源数据YUV 完整Demo] (二)音视频:MediaCodec编码桌面信息 完整Demo 进一步理解H264 (三)音视频:解析H264 SPS ...

  9. Apache Ignite与Apache Hive的个人理解与总结

    首先,贴一下官网链接辟邪:官网链接 下面,就看我强行总结吧,如果理解有误,请大佬及时指正,感激不尽! Apache Ignite是啥玩意,在上一篇已经讲过了,可能还比较易于理解:理解Ignite传送门 ...

最新文章

  1. python报错:ModuleNotFoundError: No module named cv2.cv2(bug不能加英文引号)
  2. 直播预告丨挖掘客户生命周期价值,寻迹券商业务增长
  3. [Alfred]为Baidu Weather Workflow更新图标
  4. ITK:在不复制内存的情况下为每个像素添加常量
  5. (2) 用java实现一个简易编译器1-词法解析入门
  6. 《Python编程从入门到实践》记录之将Python函数存储在模块中(import、import*)
  7. /proc/cpuinfo文件分析(查看CPU信息)
  8. php v9搜索不到内容,關於如何解決PHPCMS V9內容搜索顯示不全問題解決方案
  9. Arduino与墨子号 BC26 4G模块的对接开发
  10. 详解经典进程同步问题(生产者消费者问题/哲学家进餐问题/读者写者问题)_OS
  11. java.lang.NoSuchMethodError 之 依赖冲突解决方案
  12. 高德AR驾车导航解决方案
  13. java获取excel行数_Java如何利用POI读取Excel行数
  14. 我的世界java版如何看坐标_我的世界中怎么查看坐标,坐标系统详解
  15. ArcGIS笔记2_如何将经纬度WGS84地理坐标系转换为米单位CGCS2000投影坐标系
  16. 操作系统发展历程 (Unix、Linux、windows)
  17. Oracle 反向键索引的原理和用途(减少索引热点块)
  18. el-table表格无数据时,更改其自带的提示‘暂无数据’
  19. 试题六(java+设计模式)
  20. VS2019 配色_设计师必看|这10个网站可以帮你更快做好配色

热门文章

  1. 如何在3-5分钟之内搭建好PC/H5网站、商城、小程序、官微名片、独立后台、全员营销APP?
  2. Kindle所不为人知的一面
  3. 计算机科学有多难,自考计算机专业有多难?
  4. STM32F4+LAN8720A+STM32CubeMX+Lwip 网络通讯(以太网通讯)小实例
  5. 自动驾驶全球布局(3)传统汽车厂商
  6. 华为打造狼性团队的22条军规
  7. java中的类和对象(重点)超详细
  8. 第四章 图表样式的美化
  9. 转载nbsp;MTK存储系统相关
  10. Ardupilot 软件在环SITL仿真学习