Hive的安装与优化

HIve:

概念:
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行,数据仓库使用来做查询数据分析的数据库,基本不用来做修改,删除操作

什么是数据仓库:
数据仓库,是为了企业所有级别的决策制定过程,提供所有类型数据支持的战略集合,他是单个数据存储,出于分析性报告和决策支持的目的而建设.为需要业务智能的企业,提供指导业务流程改进,监视时间,成本,指令以及控制.
数据处理大致分两类:联机事物处理OLTP和联机分析处理OLAP

简而言之:数据仓库是用来做查询分析的数据库,基本不做操作数据库的操作

Hive执行延迟的原因:
Hive哎查询数据的时候,由于没有索引,需要扫描整张表,因此延迟比较高,还有一个原因是因为MapReduce框架本身具有较高的延迟性,因此在利MapReduce执行Hive查询的函数,会有较高的延迟.

(1) Hive处理的数据存储在HDFS上
(2) Hive分析数据底层是靠MapReduce实现的。
(3) 执行程序运行在Yarn上。

Hive:
1: 将元数据存储在数据库中,如表的名字,表的列和分区以及其属性,表的属性(是否为内外部表),表的数据所在的目录等.
2: 解释器,编译器,优化器完成HQL查询语句从此法分析,语法分析,编译,优化以及查询计划的生成,生成的查询计划存储在HDFS中,并随后又MapReduce调用执行
3:Hive将数据存储在HDFS中,大部分的查询,计算由MapReduce完成
4:执行程序在yarn上

优点:
1:操作接口采用类SQL语法,提供快速的开发能力
2:避免了去写MaoReduce,减少了开发人员的学习成本
3:Hive的延迟比较高,因此hive常用于数据分析,对实时性要求不高的场合
4:Hive的优势在与处理大数据,处理小数据么有优势,因为Hive的延迟比较高
5:Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数
6:集群可以自由拓展并具有良好的容错性,节点出现问题SQL依然可以运行
缺点:
Hive的HQL表达的能力有限
1:迭代算法无法表达
2:数据挖掘方面不擅长
Hive的效率比较低
1:Hive自动生成的MaoReduce作业,通常情况下不够智能化
2:Hive的调优比较困难

Hive架构原理:

在这里插入图片描述
用户接口:Client
用户接口主要有三个CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问hive)

元数据:Metastore
元数据包括表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等。
元数据存储在数据库中,默认存在自带的derby数据库(单用户局限性)中,推荐使用Mysql进行存储。

驱动器:Driver

(1) 解析器(SQL Parser):将SQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如ANTLR;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
(2) 编译器(Physical Plan):将AST编译生成逻辑执行计划。
(3) 优化器(Query Optimizer):对逻辑执行计划进行优化。
(4) 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于Hive来说,就是MR/Spark。

数据处理
Hive的数据存储在HDFS中,计算由MapReduce完成。HDFS和MapReduce是源码级别上的整合,两者结合最佳。
解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计划的生成。

Hive的安装:

安装单用户模式Hive:
1:安装mysql数据库:
yum install mysql-server -y
2:开启mysql服务
service mysqld start
chkconfig mysqld on
3:连接数据库:
mysql进入命令
4:查看自己有哪些数据库
show databases;
5:进入mysql
use mysql;
6:查看所有的表
show tables;
7:查看user表:
select host,user,password from user
8:修改mysql权限:
GRANT ALL PRIVILEGES ON . TO ‘root’@’%’ IDENTIFIED BY ‘123456’ WITH GRANT OPTION;
刷新
flush privileges;

9:清除其他用户
delete from user where host <> ‘%’;
10:修改用户登录密码
mysql -u root -p
创建hive所需要的库
create databas hive_remote

11:mysql和hive必须装在同一个节点上
12:上传hive压缩包并解压
cp apache-hive-1.2.1-bin -r /opt/shsxt/
13:放入软件夹里面
14:修改hive配置文件 vim hive-site.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>  
<property>  
  <name>hive.metastore.warehouse.dir</name>  
  <value>/user/hive_remote/warehouse</value>  
</property>  
   
<property>  
  <name>hive.metastore.local</name>  
  <value>true</value>  
</property>  
   
<property>  
  <name>javax.jdo.option.ConnectionURL</name>  
  <value>jdbc:mysql://node1:3306/hive_remote?createDatabaseIfNotExist=true</value>  
</property>  
   
<property>  
  <name>javax.jdo.option.ConnectionDriverName</name>  
  <value>com.mysql.jdbc.Driver</value>  
</property>  
   
<property>  
  <name>javax.jdo.option.ConnectionUserName</name>  
  <value>root</value>  
</property>  
   
<property>  
  <name>javax.jdo.option.ConnectionPassword</name>  
  <value>123456</value>  
</property>  
</configuration>

15:修改/etc/profile
添加hive的路径
source /etc/profile
拷贝JDBC的jar包进hive的lib目录里
16:
将hive lib目录里的jline-2.12.jar 覆盖掉$hadoop_home/share/hadoop/yarn/lib下jline-0.9.94.jar
rm -rf /opt/sxt/hadoop-2.6.5/share/hadoop/yarn/lib/jline-0.9.94.jar
cp /opt/sxt/hive-1.2.1/lib/jline-2.12.jar /opt/sxt/hadoop-2.6.5/share/hadoop/yarn/lib/
17:
hive
show databases;
create database sxt;
use sxt;
退出:
exit(先提交数据,在退出), quit(不提交数据,退出);

HQL 详解:

Hive数据类型:
1:基本数据类型:平常使用较多的是 int double string
在这里插入图片描述

2:集合数据类型:
array:数组
map:键值对
struct:结构体:类似于Json
三种集合数据类型可以嵌套使用

在这里插入图片描述

创建表:

1:创建表的元数据信息

create table t_user(
name string,
friends array,
children map<string,int>,
address structstreet:string,city:string
)
row format delimited fields terminated by ‘,’
collection items terminated by ‘_’
map keys terminated by ‘:’
lines terminated by ‘\n’;

创建t_user文件,添加数据
songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing
yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing

create table person(
name string,
age int,
gender string
)
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’ ;
load data local inpath ‘/root/t_user.txt’ into table t_user;
将root目录下面的t_user.txt’文件里的数据加载到表t_user中;
查询:select name ,friends[1],children[‘xiao song’],address.street from t_user;

row format delimited fields terminated by ‘,’ :每一行中的属性用,拆分
collection items terminated by ‘_’ :容器中的值用_拆分
map keys terminated by ‘:’ :map中的key与value值用:拆分
lines terminated by ‘\n’ :每一行用\n进行拆分
等我们上传完数据,查询的时候使用固定的分词来切分我们的数据

load data local inpath ‘/root/person.txt’ into table person;
将root目录下面的person文件里的数据加载到表person中;
创建 person文件,添加数据:
aa,18,男
bb,20,女

库的DDL操作:

1:创建数据库
create database sxt
create database if not exites sxt
创建了一个库相当于在HDFS上面创造了一个空的文件夹,这个文件夹用来存放表的
2:查询库的相关信息
show databases;
show databases like ‘db-s*’ 模糊查询
desc database sxt; 查询库的位置信息
use db_sxt; 切换数据库

3:修改库:
数据库的其他元数据信息都是不可更改的,包括数据库名和数据库所在的目录位置

4:删除数据库(drop)::
drop database db_hive2;
drop database if exists db_hive2;
drop database if exists db_sxt cascade; 如果数据库里面不为空(有表) 用cascade强制性删除(慎用)

表的DDL操作:

1:创建表(重要)

CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
[(col_name data_type [COMMENT col_comment], …)]
[COMMENT table_comment]
[PARTITIONED BY (col_name data_type [COMMENT col_comment], …)]
[CLUSTERED BY (col_name, col_name, …)
[SORTED BY (col_name [ASC|DESC], …)] INTO num_buckets BUCKETS]
[ROW FORMAT row_format]
[STORED AS file_format]
[LOCATION hdfs_path]

CREATE 创建
[EXTERNAL] 外部的,如果不适用默认创建的为内部表
TABLE 关键字
[IF NOT EXISTS] 当这个表不存在的时候
table_name 表名,注意语法规则

[(col_name data_type [COMMENT col_comment], …)]
col_name 列的名字
data_type 数据类型
[COMMENT col_comment] 列的注释信息
[COMMENT table_comment] 表的注释信息
PARTITIONED BY :创建分区表
CLUSTERED BY :创建分桶表
[ROW FORMAT row_format] :数据的切分格式
DELIMITED
[FIELDS TERMINATED BY char] 列的切分标准
[COLLECTION ITEMS TERMINATED BY char] 容器的切分标准
[MAP KEYS TERMINATED BY char] map的切分标准
[LINES TERMINATED BY char]每一行的切分标准
[STORED AS file_format] 数据存放的格式,有可能涉及到数据的序列化和反序列化
[LOCATION hdfs_path] 自定义数据存放的位置

内部表;默认创建的都是内部表
1:hive会控制表的元数据信息和数据信息
2:当删除表的时候,会同时删除表的元数据信息和数据信息
3:内部表不适合和其他工具共享数据

外部表(重要):
1:hive会控制表的元数据信息,但不会管理表的数据信息
2:当删除表的时候只会删除表的元数据信息,不会删除信息
3:可以在创建外部表的时候直接指定一个目录(外部表的数据目录),当数据产生程序可以直接将数据放到目录里
4:我们可以直接对hive中的数据直接查询,而且删除的时候数据不会被破坏

创建一个外部表:
create EXTERNAL table ext_person(
name string,
age int,
gender string
)
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’
location ‘/user/root/person’;
(location '/user/root/person person指的是文件夹,把数据放进文件夹里面,然后在hive里面直接查询就更好了,这样就不需要 load data…加载数了,数据默认存放在 /user/hive_remote/warehouse/库名/ 但是外部表可以指定修改文件存放路径)

查询表的类型:
desc formatted etc_person;
在这里插入图片描述

外部表和内部表的相互转换:
内部变外部
alter table ext_person set tblproperties(‘EXTERNAL’=‘TRUE’);
外部变内部
alter table ext_person set tblproperties(‘EXTERNAL’=‘FALSE’);

删除表:
drop table if exists person;
表的重命名:
ALTER TABLE table_name RENAME TO new_table_name
ALTER TABLE person RENAME TO ext_person
表中列信息修改:
更新列:
ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name];
alter table person change name pname string;
增加/替换列:
ALTER TABLE table_name ADD|REPLACE COLUMNS (col_name data_type [COMMENT col_comment], …);
alter table person add age int;

表的查询:
show tables like ‘ext_*’;

数据的更新和删除(用的少)
直接删除表

DML:
数据的加载:
Hive不能很好的支持用insert语句一条一条的进行插入操作(效率太低,而且会产生新的数据文件存放插入的数据),不支持update操作。数据是以load的方式加载到建立好的表中。数据一旦导入就不可以修改
hive> load data [local] inpath ‘/opt/module/datas/student.txt’ overwrite | into table student [partition (partcol1=val1,…)];
insret:
insert into person values(‘gx’,58,‘男’);
load:
load data:表示加载数据
local:表示从本地加载数据到hive表;否则从HDFS加载数据到hive表,而且会会将源数据删除
inpath:表示加载数据的路径
overwrite:表示覆盖表中已有数据
into 追加,即使同名,将新文件改名后追加
student:表示具体的表

数据的导出:

1:建数据导出到本地(/user/root/student 目录下):
insert overwrite local directory ‘/user/root/person’ select * from person;
将查询的结果格式化导出到本地(/user/root/student1 目录下):
insert overwrite local directory ‘/user/root/person1’ ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’ select * from person;
2:导出到hdfs集群:
insert overwrite directory ‘/user/root/person2’ ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’ select * from person;

Hive分区表!(非常重要):

分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多.(为了提高数据查询分析的效率,将数据有策略的放到不同的分区中(hdfs的一个子文件目录),分区就是将一个大文件切分成许多的小文件)

可在表定义时创建partition ,也可在以后添加分区
分区分为:单分区和多分区。
静态分区(SP)static partition和动态分区(DP)dynamic partition。

单分区:

1;创建分区:

create table student(
sname string,
age int
)
partitioned by(
addr string
)
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’;

sgb,88,sx
jzy,86,sx
hfh,88,jz
sh,86,jz
进行分区
load data inpath ‘/user/root/student.txt’ into table student partition(addr=‘sx’);
load data inpath ‘/user/root/student.txt’ into table student partition(addr=‘jz’);
扫描当前文件夹子目录
select * from student;
查看指定分区
select * from student where addr=‘sx’;

多分区:
1:创建表格
create table teacher(
sname string,
age int
)
partitioned by(
grade string,
clazz string
)
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’;

sgb11,88,ge,yb
jzy11,86,ge,yb

sgb12,88,gy,yb
jzy12,86,gy,yb

sgb21,88,ge,eb
jzy21,86,ge,eb

加载数据:
load data inpath ‘/user/root/teacher.txt’ into table teacher partition(grade=‘gy’,clazz=‘yb’);
load data inpath ‘/user/root/teacher.txt’ into table teacher partition(grade=‘gy’,clazz=‘eb’);
load data inpath ‘/user/root/teacher.txt’ into table teacher partition(grade=‘ge’,clazz=‘yb’);

动态分区:
静态分区与动态分区最主要的区别在与静态分区是手动指定的,而动态分区是通过数据来进行判断(自动的分进我们想要的分区中去),详细来说,静态分区的列是在编译时期,通过用户传递来决定的,动态分区只有在SQL执行时才能决定
开启动态分区首先在hive会话中设置如下的参数:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
其余参数如下:
在这里插入图片描述
设置动态分区:
1:设置hive的参数:
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
2:创建两张表,一张真实设置动态分区的表,一张临时的表,然后在临时表中插入数据,然后在重临时表中查询数据into/overwrite 到真实的表中.
3:创建表:(设置动态分区的表)
create table dy_teacher(
sname string,
age int
)
partitioned by(
grade string,
clazz string
)
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’;

(临时表:)
create external table dy_teacher_tmp(
sname string,
age int,
grade string,
clazz string
)
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’
location ‘/user/root/teacher/’;

4:设置数据文件,放在hdfs的user/root/teacher/ 下面
sgb11,88,g1,1b
jzy11,86,g1,1b
sgb12,88,g1,2b
jzy12,86,g1,2b
sgb21,88,g2,1b
jzy22,86,g2,2b

把从dy_teacher中查询到数据 按照分区插入到dy_teacher表中

insert into table dy_teacher partition(garde,clazz) select * from dy_teacher;
在’/user/root/teacher/'下面在放数据 外部表(临时表 直接select直接查询就行了)
insert overwrite table dy_teacher partition(garde,clazz) select * from dy_teacher;

Hive SerDe:

Hive SerDe - Serializer and Deserializer SerDe 用于做序列化和反序列化

查询:

同sql一样,select * from 表; 亦可指定查询字段。
注意点:
(1)SQL 语言大小写不敏感。
(2)SQL 可以写在一行或者多行
(3)关键字不能被缩写也不能分行
(4)各子句一般要分行写。
(5)使用缩进提高语句的可读性。

常用函数:
总函数:count()-----count(*)
最大值:max-----max(字段)
最小值:min----min(字段)
总和:sum------sum(字段)
平均值:avg----avg(字段)
空字段赋值:
格式: NVL( string1, replace_with)
如果不为null,则返回string1的值,为null的话 返回 replace_with的值;

内置函数:
spilt: 切分

create table movie(
name string,
type string
)
row format delimited fields terminated by ’ ’
lines terminated by ‘\n’;

movie.txt的数据

搏击俱乐部 悬疑,剧情,格斗
穆赫兰道 悬疑,福利
恐怖游轮 悬疑,恐怖,惊悚,烧脑,剧情
教父 黑帮,枪战,福利
加载user/root下面的文件 movie的数据到表movie中
load data inpath ‘/user/root/movie.txt’ into table movie;
对类型按照,切分 查询
select split(type,’,’) from movie;
在这里插入图片描述
对类型按照,切分并和name匹配
select name.split(type,’,’) from movie;
在这里插入图片描述
将按照类型切分的数据进行展开
select explode(split(type,’,’)) from movie;
在这里插入图片描述
Lateral View:
Lateral View主要用来解决select在使用UDTF函数做查询的过程中,查询只能包含单个UDTF不能包含其他字段以及多个UDTF函数同时使用的问题

语法:
LATERAL VIEW udtf(expression) tableAlias AS columnAlias (’,’ columnAlias)
伪表:
按照类型的,进行切分并展开 起个别名 sxt 然后查询sxt
select sxt from movie lateral view explode(split(type,’,’)) tableAlias as sxt;
按照类型的,进行切分并展开 起个别名 sxt 然后查询sxt和name
select name,sxt from movie lateral view explode(split(type,’,’)) tableAlias as sxt;
在这里插入图片描述
例题2 :
搏击俱乐部 悬疑,剧情,格斗 v1:12,v2:22
穆赫兰道 悬疑,福利 v1:13,v2:23
恐怖游轮 悬疑,恐怖,惊悚,烧脑,剧情 v1:14,v2:24
教父 黑帮,枪战,福利 v1:15,v2:25

create table movie2(
name string,
type array,
ver map<string,string>
)
row format delimited fields terminated by ’ ’
collection items terminated by ‘,’
map keys terminated by ‘:’
lines terminated by ‘\n’;

load data inpath ‘/user/root/movie2.txt’ into table movie2;

select name,tt,vv,vt from movie2
lateral view explode(type) movie_type as tt
lateral view explode(ver) movie_ver as vv , vt;

例题三:
1:创建表
create table worldcount(
line string
)
2:加载数据
load data inpath ‘/user/root/harry.txt’ into table worldcount;
3:拆解
按照行的空格进行切分
select split(line," “) from worldcount;
把切分的数据展开
select explode(split(line,” “)) from worldcount;
设置一个伪列,并查询
select world select world,count(world) from worldcount
按照单词进行分组,查询每个单词的个数
select world,count(world) from worldcount
lateral view explode(split(line,” ")) worldcount_world as world
group by world;

总结: explode就是把东西爆裂开(就是把东西竖行排列)
split(line,’,’): 把line按照,进行切分
explode(split(line,’,’))把line按照逗号进行切分,然后竖行排列
把line按照逗号进行切分,然后竖行排列的列起一个别名 ss 里面有所有竖行排列的数据
lateral view explode(split(line,’,’)) tables Alines as ss;
查询worldcount中的ss(ss是 把line按照逗号进行切分,然后竖行排列的列起一个别名 ss 里面有所有竖行排列的数据)
select ss from worldcount lateral view explode(split(line,’,’)) tables Alines as ss;

例题四: Hive实现基站的掉线率 找出掉线率最高的前10基站

record_time:通话时间
imei:基站编号
cell:手机编号
drop_num:掉话的秒数
duration:通话持续总秒数

2011-07-13 00:00:00+08,356966,29448-37062,0,0,0,12,100,G,0
2011-07-13 00:00:00+08,352024,29448-51331,0,0,0,13,100,G,0
2011-07-13 00:00:00+08,353736,29448-51331,0,0,0,11,100,G,0
2011-07-13 00:00:00+08,353736,29448-51333,0,0,0,14,100,G,0
2011-07-13 00:00:00+08,351545,29448-51333,0,0,0,15,100,G,0
2011-07-13 00:00:00+08,353736,29448-51343,1,0,0,11,100,G,0
2011-07-13 00:00:00+08,359681,29448-51462,0,0,0,0,100,G,0
2011-07-13 00:00:00+08,359681,29448-51462,0,0,0,0,0,G,0
2011-07-13 00:00:00+08,354707,29448-51462,0,0,0,11,100,G,0
2011-07-13 00:00:00+08,356137,29448-51470,0,0,0,19,100,G,0

1:创建表
create table imeidrop(
record_time string,
imei string,
cell string,
ph_num int,
call_num int,
drop_num int,
duration int,
drop_rate DOUBLE,
net_type string,
erl string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘,’
lines terminated by ‘\n’;
2:加载数据
3:查询
select imei,sum(drop_num),sum(duration),sum(drop_num)/sum(duration) ss from imeidrop where drop_num>0 or duration>0
group by imei order by ss desc limit 10;

桶:

分区针对的是数据存储路径,粪桶针对的数据文件
分同表时对列取哈希值的方式,将不同的数据放进不同的文件中存储(可以自己设置)
对于hive中的每一个表,分区点都可以进一步进行分桶由列的哈希值除以桶的个数来决定条数据划分在哪个桶里面.
分桶的好处:
减少每个文件的数据量
方便执行map-join
数据抽样:
TABLESAMPLE(BUCKET x OUT OF y)
x:表示从哪个bucket开始抽取数据
y:必须为该表总bucket数的倍数或因子
1,3: 有三个桶,取出第一个桶的数据
2,3: 有三个桶,取值第二个桶的数据
从Y个桶里面取值第x个桶的数据
设置参数:set hive.enforce.bucketing=true;默认:false;设置为true之后,mr运行时会根据bucket的个数自动分配reduce task个数(用户也可以通过mapred.reduce.tasks自己设置reduce任务个数,但分桶时不推荐使用)一次作业产生的桶(文件数量)和reduce task个数一致

1:设置参数:set hive.enforce.bucketing=true
设置参数 将开启和桶数量相等的reduceTask去处理数据,一个reduceTask生成一个文件
2:创建两张表:
真实表:(不用加载数据)
create table sxtbucket(
sname string,
age int,
grade string,
clazz string
)
按照grade分为三个桶之后按照clazz排序
clustered by(grade) sorted by(clazz) into 3 buckets
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’;

3:创建临时表:
create external table sxtbucket_tmp(
sname string,
age int,
grade string,
clazz string
)
row format delimited fields terminated by ‘,’
lines terminated by ‘\n’
location ‘/user/root/sxtbucket’;
4:读出临时表的数据给真实表插入数据
insert into table sxtbucket select * from sxtbucket_tmp;

数据抽样的计算:
select * from sxtbucket;
select * from sxtbucket tablesample(bucket 2 out of 3);

–创建num表
create table sxtnum(
num int
)
clustered by(num) sorted by(num desc) into 6 buckets
ROW FORMAT DELIMITED lines terminated by ‘\n’;

–创建临时表
create external table sxtnum_tmp(
num int
)
ROW FORMAT DELIMITED fields terminated by ‘,’
lines terminated by ‘\n’
location ‘/user/root/num/’;

–插入数据
insert into table sxtnum select * from sxtnum_tmp;

Hive的优化:

核心思想: 把HiveSQL当做MapReduce程序去优化

热点现象:

什么是热点现象:
当大量的client访问hbase集群中的某个或者少个region的时候,造成少数region server的读写请求过多,负载过大,而其它的region server 负载却很小,就容易造成特点现象.造成热点现象的主要原因:
1: hbase中的数据值按照字典顺序排列的,当大量的,连续的rowkey集中写在个别的region中,各个region中的数据分布不均衡
2: 创建表的时候没有预分区,创建表的时候,只有一个region,大量的数据写入当前的region
3: 设计的rowkey不合理(最主要的原因)
4:解决方法; Rowkey的随机 散列+ 创建预分区

预分区:
在创建hbase时,就预先根据可能的rowkey划分出多个region而不是默认的一个region,从而可以将后续的读写操作负载均衡到不同的region上,避免热点现象.

以下SQL 不会转为MapReduce来执行():

1:select 仅查询本表字段
2:where 仅对本表字段进行过滤
explain: 显示执行计划:
例如:explain select * from person;

Fetch:
select* from 表,这样的情况中,hive可以直接读取表中在hdfs中对应数据文件的内容,直接将查询结果打印到控制台即可,就是直接去hdfs直接拉取数据.
在hive-default.xml.template文件中hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。

a) 把hive.fetch.task.conversion设置成none,然后执行查询语句,查查字段都会执行mapreduce程序
b) 把hive.fetch.task.conversion设置成more,然后执行查询语句,查
查字段都不会执行mapreduce程序

HIve的运行方式:

1:本地模式
2:集群模式
有一些简单的查询以及或者表的数据文件小于128MB的时候,用本地模式会快很多,不会开启MapReduce去计算
开启本地模式: set hive.exec.mode.local.auto=true;
(查看本地模式是否开启 用set set hive.exec.mode.local.auto)
注意:hive.exec.mode.local.auto.inputbyts.m的最大值(即用本地模式运行的话,表中的数据(加载文件)最大值不能超过128MB,若是超过128MB,还是会一集群的方式来运行)

并行计算:
设置参数开启并行模式:
set hive.exec.parallel=true; 打开任务并执行

下面两个sql执行语句之间并没有什么关系,所以可以开启并行模式,一次运行两个job,这样运行速度会比较块,一般一次SQL计算中允许比并行执行的job的最大值为8 ,当然这个值是可以人为设置的.
当然,得是在系统资源比较空闲的时候才有优势,否则,没资源,并行也起不来。
hive.exec.parallel.thread.number

Select t1.cf1,t2.cf2 from
(select count(id) as cf1 from table1) t1,
(select count(id) as cf2 from table1) t2,

严格模式:
可以阻止用户执行那些可能意想不到的不好的影响查询
通过设置参数的方式开启严格模式: set hive.mapred.mode=strict;(默认nonstrict是非严格模式)
严格模式的作用: 查询限制:

1:对于分区表,必须添加where对于分区子弹进行过滤(简单来说,就是不允许用户扫描所有分区,因为通常分区都有非常大的数据集,所以不进行限制可能会小韩令人想想不带的巨大资源来处理这个请求)
2:order by 语句必须包含limit输出限制(因为order by 为了执行排序的过程会将所有的结果数据发送到同一个rreduce中处理,强制要求用户增加这个limit语句可以防止reduce额外执行一段很长的时间,直接查询需要的那些数据就好了)

3:限制笛卡尔积的查询
HIve排序:
order by:对于查询结果做全排序,只允许一份reduce处理
(数据量较大时,应慎用,严格模式下,必须结合limit来使用)
Sort by: 对于单个reduce进行排序
distribute by : 分区进行排序,经常和Sort by 结合使用
Cluster by: 相当于Sort by + distribute by(Cluster by 不能通过asc desc的方式制定排序规则,可以通过distribute by column sort by column asc|desc的方式 进行排序)

4: Map-Side聚合:
默认情况下,Map阶段同一个key数据发送给一个reduce,当key的数据过大时就会造成数据倾斜,并不是所有的聚合操作都需要在reduce中完成的,很多聚合操作都是可以先在map阶段进行部分聚合,最终在reduce端得出最终的结果

1.开启Map端聚合参数设置:
set hive.map.aggr=true;
相关的参数配置:
在这里插入图片描述
控制Hive中的Map与Reduce的数量:

Map数量相关的参数:
mapred.max.split.sixe: 一个split的最大值,即每个map处理文件的最大值
mapred.min.split.size.per.node : 一个节点上split上的最最小值
mapred.min.split.sixe.per.rack: 一个机架上split的最小值

Redecue数量相关的参数设置:
mapred.reduce.tasks : 强制指定reduce的数量
hive.exec.reduces.bytes.per.reduce: 每一个reduce处理的数据量
hive.exec.reducers.max: 每个人物最大的reducea数

合理设置Reduce数:
在这里插入图片描述

reduce的数量并不是越多越好,合理的安排设置reduce的数量,因为过多的启动和初始化reduce也会消耗时间和资源,而且有多少个reduce,就会有多少个输出文件,如果生成很多的小文件,那么如果这些小文件作为下一以任务的输出,则也会有小文件过多的情况在设置reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的reduce数;使单个reduce任务处理数据量大小要合适;

小文件进行合并:
在map执行前合并小文件,减少map的数量:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)HiveInputFormat没有对小文件合并功能
set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

Hive- JVM重用:
当小文件过着task过多的时候,hadoop默认配置通常是派生JVM来执行Map与Reduce,一个task伴随着一次JVM的启动与销毁,当一个job中与成千上万个task的时候,那就会伴随着成千上万次的JVM的启动销货,而JVM的重用,就是让一个JVM在同一个job重复执行多次,这样无形中就节省了很多的时间与资源

适用场景:1 小文件个数过多 2: task个数过多

通过set mapred.job.reuse.jvm.num.tasks=n 来设置(n是task插槽个数)
缺点: 设置开启后,task插槽会一直占用资源,不论是否有task运行,直到所有的task即真个job全部执行完后才时,才会释放所有的task插槽资源

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值