天天看点

hive的进一步理解HIVE的基本理解,使用,特性HIVE动态分区HIVE锁表问题HIVE数据倾斜hql性能调优hive 小表与大表关联执行MR或聚集查询卡死

目录

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

什么是hive

hive元数据

hive默认分隔符   \001

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

hive/mysql/hbase比较

函数

hive解决wordcount案例

hive内部表与外部表

hql特性:

hive常用命令:

读取数据文件方法:

查看yarn mr日志

HIVE动态分区

HIVE锁表问题

HIVE数据倾斜

hql性能调优

hive 小表与大表关联

执行MR或聚集查询卡死

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                解析json: get_json_object

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               连续排序(最大排名会小于总数)

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的日志:

[[email protected] ~]$ yarn logs -applicationId application_1523430872525_0002 

查看具体某一个container的日志:

[[email protected] ~]$ yarn logs -applicationId application_1523430872525_0002 -containerId container_1523191604137_0016_02_000001 -nodeAddress hadoop01:60127
           

HIVE动态分区

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操作

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

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

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

hql性能调优

 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适用的场景:   关联操作中有一张表非常小;不等值的链接操作

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

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

4.小文件

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

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

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

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

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

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

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

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

hive 小表与大表关联

关于小表join大表的补充:

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

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

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

执行MR或聚集查询卡死

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

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

继续阅读