hive的进一步理解

目录

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比较

hivemysqlhbase
数据量
速度数据量大时快数据量小时快
查询增删改增删改

函数

系统函数: 月: 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.75
    studentid=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.6666666666666666
        cume_dist2=大于等于80的人数为4/总人数9=0.4444444444444444
        cume_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组后,当前行的组排名为2
        ntile2:对分区的数据均匀分成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;  #开启动态分区,默认是false
 set hive.exec.dynamic.partition.mode=nonstrict; #开启允许所有分区都是动态的,否则必须要有静态分区才能使用。
 insert overwrite table dpartition
 partition(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_parttion
 partition(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_parttion
 partition(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  5m
 
join table_2
 
on 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问题:


1Sort 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排好序的。

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

3Distrbute 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值