HIVE

  1. Hive是Apache提供的基于Hadoop的数据仓库工具。
  2. Hive提供了类sql语言来对分布式系统中的数据来进行读写以及管理
  3. Hive将SQL语句在底层转化为MapReduce程序来操作数据
  4. Hive的出现降低了离线分析的门槛

数据仓库

数据库数据仓库
数据量千万级别,GB起始量从TB开始
数据来源来源单一,实时捕获数据数据来源多样,存储的历史数据
事务强调事务弱事务甚至是没有事务
面向对象开发人员客户,管理人员
操作提供了完整的增删改查的能力增加,查询,往往不支持单条数据的删除和改动
场景OLTP系统(Online Transaction Processor联机事务处理)OLAP(Online Analysis Processor-联机分析处理系统)
根据业务建立对应的表结构维度表以及事实表

在Hive中每建立一个库,都会在HDFS对应的创建一个目录
在Hive中没有主键的概念。
Hive中的每一张表在HDFS上都会对应一个目录。
当利用Hive管理本地数据的时候,会将要管理的数据上传到HDFS上
当一张表已经创建好之后,这个表中的字段就不允许修改。
从Hive查询数据向本地目录中写的时候只能覆盖。
SerDe - Serializer Deserializer:
a. 专门针对不规律的数据进行字段提取,需要注意的是在提取的时候需要指定提取的与此同时表达式。
b.在提取的时候,与此同时表达式中的每一个捕获组对应Hive组中一个字段

  • 建表语句,指定分隔符
    create table student(id int,name string,age int) row format delimited fields terminated by ’ ';
  • 加载本地数据,/home/stu.txt 内容:2 jack 20
    load data local inpath ‘/home/stu.txt’ into table student;
  • 创建stu2和student表结构一致
    create table stu2 like student;
  • 从表中复制数据
    insert into table stu2 select * from student where id>1;
  • 复制数据到本地文件
    insert overwrite local directory ‘/home/hivedata’ row format delimited fields terminated by ‘,’ select * from student;
  • 向多个表插数据
    from student insert into stu2 select * where id >1 insert into stu3 select * where name =‘jack’;
  • 写到HDFS
    insert overwrite directory ‘/student’ row format delimited fields terminated by ’ ’ select * from student;
  • 重命名表
    alter table student rename to stu1;
  • 添加表字段
    alter table stu1 add columns(gender string);
  • 格式化数据
    create table log(host string,time string,timezone string,request string,resource string,protocol string,state int) row format serde ‘org.apache.hadoop.hive.serde2.RegexSerDe’ with serdeproperties(“input.regex”="(.) -- \[(.) (.)\] "(.) (.) (.)" ([0-9]+) -") stored as textfile;
    load data local inpath ‘/home/mydata/log.txt’ into table log;
    log.txt中内容如下
192.168.120.23 -- [30/Apr/2018:20:25:32 +0800] "GET /asf.avi HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:32 +0800] "GET /bupper.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:32 +0800] "GET /bupper.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /bg-button HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /bbutton.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /asf.jpg HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tomcat.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tomcat.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tbutton.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tinput.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:33 +0800] "GET /tbg.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /tomcat.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /bg.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /bg-button.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /bg-input.css HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /bd-input.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /bg-input.png HTTP/1.1" 304 -
192.168.120.23 -- [30/Apr/2018:20:25:34 +0800] "GET /music.mp3 HTTP/1.1" 304 -

表结构

  1. 内部表:在Hive中创建的存储在/user/hive/warehouse路径下的表。删除内部表时,对应的目录也会被删除掉。
  2. 外部表:利用Hive的表结构管理HDFS上已经存在的表。创建外部表的时候指定的路径必须是一个目录,无法指定到具体的文件。在Hive中删除外部表的时候,对应的目录不会被删除。
  3. 分区表
    用于对数据进行分类
    分区表的字段在原始数据中是不存在的
  • 外部表 /score为文件夹
create external table score(name string,chinese int,math int,english int) row format delimited fields terminated by ' ' location '/score'
  • score内有score.txt,内容如下:
Bob 90 64 92
Alex 64 63 68
Grace 57 86 24
Henry 39 79 78
Adair 88 82 64
Chad 66 74 37
Colin 64 86 74
Eden 71 85 43
Grover 99 86 43
  • 分区表(country字段在元数据中不存在)
create table person(id int,name string ) partitioned by(country string)row format delimited fields terminated by ' ';
load data local inpath '/home/mydata/p.txt' into table person partition(country='en');
  • 添加一个分区(手动创建的分区目录)
alter table person add partition (country='jp') location '/user/hive/warehouse/hivedemo.db/person/country=jp' ;
msck repair table person;
  • 分区改名
alter table person partition(country='jp') rename to partition(country='kn')
  • 分区表2
    p2.txt内容:
1 amy cn
2 sam us
3 alex en
4 bob cn
5 helen cn
6 grace en
7 jack jp

加载的数据不是分区的。要把p2加载到分区表person中:

create table p2(id int,name string,country string)row format delimited fields terminated by ' '
load data local inpath '/home/mydata/p2.txt' into table p2

开启动态分区,设置为非严格模式

set hive.exec.dynamic.partition = true;
set hive.exec.dynamic.partition.mode=nonstrict ;

将p2数据插入到分区表person中

insert into table person partition(country) select * from p2 distribute by(country);

分桶表

  1. 将数据分到不同的bucket(桶)中,主要作用是进行抽样
  2. 一个表既可以分区也可以分桶
  3. 分桶表通过hash分桶算法,将数据分放在不同的桶(hdfs中的文件)中,方便后续获取
  4. 分桶表机制默认是不开启的,需要手动开启:set hive.enforce.bucketing=true;
  5. 分桶表不允许以外部文件方式导入数据,只能从另外一张表数据导入
  • 创建分桶表
create table p3(id int,name string,country string) clustered by (name) into 6 buckets row format delimited fields terminated by ' ';
 insert into p3 select * from p2 ;
 select * from p3 tablesample(bucket 1 out of 3 on name);

bucket x out of y
x:决定抽样的起始桶
y:决定的是抽样的比例,y必须是桶数的因数或者倍数。
6buckets,
1 out of 3 --从1号桶开始,抽取6/3=2个桶的数据–1,4
1 out of 12–从1号桶开始,抽取6/12-1/2个桶的数据。
4 out of 18–从4号桶开始抽取,抽取6/18=1/3个桶的数据。

join

create external table orders(oid int,time string,pid int,num int)row format delimited fields terminated by ' ' location '/orders';
create external table products (pid int,name string,price double)row format delimited fields terminated by ' ' location '/products';
select o.oid,o.num*p.price from orders o join products p on o.pid =p.pid;

semi join

左边哪些出现在了右表中。

select * from orders o left semi join products p on o.pid = p.pid

数组

1,2,3 4,5,6
2,2,2,2 3,4,5,2

create table nums(n1 array<int>,n2 arr<int>) row format delimited fields terminated by ' ' collection items terminated by ',';
load data local inpath '/home/mydata/nums.txt' into table nums;

select n1[0] from nums;

映射

vim map.txt

1 tom:class1
2 amy:class2
3 alex:class1

创建映射表

create table maps(id int ,info map<string,string>) row format delimited fields terminated by ' ' map keys terminated by ':';
load data local inpath '/home/mydata/map.txt' into table maps;
select info['tom'] from maps;
select info['tom'] from maps where info['tom'] is not null;

struct 类型

score

Bob 90 64 92
Alex 64 63 68
Grace 57 86 24
Henry 39 79 78
Adair 88 82 64
Chad 66 74 37
Colin 64 86 74
Eden 71 85 43
Grover 99 86 43
create external table score(info struct<name:string,chinese:int,math:int,english:int>) row format delimited fields terminated by '.' collection items terminated by ' ' location '/score';
select info.name from score

函数

21

=================

一、数学函数

返回类型函数说明
BIGINTround(double a)四舍五入
DOUBLEround(double a, int d)小数部分d位之后数字四舍五入,例如round(21.263,2),返回21.26
BIGINTfloor(double a)对给定数据进行向下舍入最接近的整数。例如floor(21.2),返回21。
BIGINTceil(double a), ceiling(double a)将参数向上舍入为最接近的整数。例如ceil(21.2),返回23.
doublerand(), rand(int seed)返回大于或等于0且小于1的平均分布随机数(依重新计算而变)
doubleexp(double a)返回e的n次方
doubleln(double a)返回给定数值的自然对数
doublelog10(double a)返回给定数值的以10为底自然对数
doublelog2(double a)返回给定数值的以2为底自然对数
doublelog(double base, double a)返回给定底数及指数返回自然对数
doublepow(double a, double p) power(double a, double p)返回某数的乘幂
doublesqrt(double a)返回数值的平方根
stringbin(BIGINT a)返回二进制格式
stringhex(BIGINT a) hex(string a)将整数或字符转换为十六进制格式
stringunhex(string a)十六进制字符转换由数字表示的字符。
stringconv(BIGINT num, int from_base, int to_base)将指定数值,由原来的度量体系转换为指定的试题体系。例如CONV(‘a’,16,2),返回
doubleabs(double a)取绝对值
int doublepmod(int a, int b) pmod(double a, double b)返回a除b的余数的绝对值
doublesin(double a)返回给定角度的正弦值
doubleasin(double a)返回x的反正弦,即是X。如果X是在-1到1的正弦值,返回NULL。
doublecos(double a)返回余弦
doubleacos(double a)返回X的反余弦,即余弦是X,,如果-1<= A <= 1,否则返回null.
int doublepositive(int a) positive(double a)返回A的值,例如positive(2),返回2。
int doublenegative(int a) negative(double a)返回A的相反数,例如negative(2),返回-2。

二、类型转换函数

返回类型函数说明
指定 “type”cast(expr as )类型转换。例如将字符”1″转换为整数:cast(’1′ as bigint),如果转换失败返回NULL。

三、日期函数

返回类型函数说明
stringfrom_unixtime(bigint unixtime[, string format])UNIX_TIMESTAMP参数表示返回一个值’YYYY- MM – DD HH:MM:SS’或YYYYMMDDHHMMSS.uuuuuu格式,这取决于是否是在一个字符串或数字语境中使用的功能。该值表示在当前的时区。
bigintunix_timestamp()如果不带参数的调用,返回一个Unix时间戳(从’1970- 01 – 0100:00:00′到现在的UTC秒数)为无符号整数。
bigintunix_timestamp(string date)指定日期参数调用UNIX_TIMESTAMP(),它返回参数值’1970- 01 – 0100:00:00′到指定日期的秒数。
bigintunix_timestamp(string date, string pattern)指定时间输入格式,返回到1970年秒数:unix_timestamp(’2009-03-20′, ‘yyyy-MM-dd’) = 1237532400
stringto_date(string timestamp)返回时间中的年月日: to_date(“1970-01-01 00:00:00″) = “1970-01-01″
stringto_dates(string date)给定一个日期date,返回一个天数(0年以来的天数)
intyear(string date)返回指定时间的年份,范围在1000到9999,或为”零”日期的0。
intmonth(string date)返回指定时间的月份,范围为1至12月,或0一个月的一部分,如’0000-00-00′或’2008-00-00′的日期。
intday(string date) dayofmonth(date)返回指定时间的日期
inthour(string date)返回指定时间的小时,范围为0到23。
intminute(string date)返回指定时间的分钟,范围为0到59。
intsecond(string date)返回指定时间的秒,范围为0到59。
intweekofyear(string date)返回指定日期所在一年中的星期号,范围为0到53。
intdatediff(string enddate, string startdate)两个时间参数的日期之差。
intdate_add(string startdate, int days)给定时间,在此基础上加上指定的时间段。
intdate_sub(string startdate, int days)给定时间,在此基础上减去指定的时间段。

四、条件函数

返回类型函数说明
Tif(boolean testCondition, T valueTrue, T valueFalseOrNull)判断是否满足条件,如果满足返回一个值,如果不满足则返回另一个值。
TCOALESCE(T v1, T v2, …)返回一组数据中,第一个不为NULL的值,如果均为NULL,返回NULL。
TCASE a WHEN b THEN c [WHEN d THEN e]* [ELSE f] END当a=b时,返回c;当a=d时,返回e,否则返回f。
TCASE WHEN a THEN b [WHEN c THEN d]* [ELSE e] END当值为a时返回b,当值为c时返回d。否则返回e。

五、字符串函数

返回类型函数说明
intlength(string A)返回字符串的长度
stringreverse(string A)返回倒序字符串
stringconcat(string A, string B…)连接多个字符串,合并为一个字符串,可以接受任意数量的输入字符串
stringconcat_ws(string SEP, string A, string B…)链接多个字符串,字符串之间以指定的分隔符分开。
stringsubstr(string A, int start) substring(string A, int start)从文本字符串中指定的起始位置后的字符。
stringsubstr(string A, int start, int len) substring(string A, int start, int len)从文本字符串中指定的位置指定长度的字符。
stringupper(string A) ucase(string A)将文本字符串转换成字母全部大写形式
stringlower(string A) lcase(string A)将文本字符串转换成字母全部小写形式
stringtrim(string A)删除字符串两端的空格,字符之间的空格保留
stringltrim(string A)删除字符串左边的空格,其他的空格保留
stringrtrim(string A)删除字符串右边的空格,其他的空格保留
stringregexp_replace(string A, string B, string C)字符串A中的B字符被C字符替代
stringregexp_extract(string subject, string pattern, int index)通过下标返回正则表达式指定的部分。regexp_extract(‘foothebar’, ‘foo(.*?)(bar)’, 2) returns ‘bar.’
stringparse_url(string urlString, string partToExtract [, string keyToExtract])返回URL指定的部分。parse_url(‘http://facebook.com/path1/p.php?k1=v1&k2=v2#Ref1′, ‘HOST’) 返回:’facebook.com’
stringget_json_object(string json_string, string path)select a.timestamp, get_json_object(a.appevents, ‘ . e v e n t i d ’ ) , g e t j s o n o b j e c t ( a . a p p e n v e t s , ‘ .eventid’), get_json_object(a.appenvets, ‘ .eventid),getjsonobject(a.appenvets,.eventname’) from log a;
stringspace(int n)返回指定数量的空格
stringrepeat(string str, int n)重复N次字符串
intascii(string str)返回字符串中首字符的数字值
stringlpad(string str, int len, string pad)返回指定长度的字符串,给定字符串长度小于指定长度时,由指定字符从左侧填补。
stringrpad(string str, int len, string pad)返回指定长度的字符串,给定字符串长度小于指定长度时,由指定字符从右侧填补。
arraysplit(string str, string pat)将字符串转换为数组。
intfind_in_set(string str, string strList)返回字符串str第一次在strlist出现的位置。如果任一参数为NULL,返回NULL;如果第一个参数包含逗号,返回0。
array<array>sentences(string str, string lang, string locale)将字符串中内容按语句分组,每个单词间以逗号分隔,最后返回数组。 例如sentences(‘Hello there! How are you?’) 返回:( (“Hello”, “there”), (“How”, “are”, “you”) )
array<struct<string,double>>ngrams(array<array>, int N, int K, int pf)SELECT ngrams(sentences(lower(tweet)), 2, 100 [, 1000]) FROM twitter;
array<struct<string,double>>context_ngrams(array<array>, array, int K, int pf)SELECT context_ngrams(sentences(lower(tweet)), array(null,null), 100, [, 1000]) FROM twitter;

六、聚合函数

返回类型函数说明
bigintcount(*) , count(expr), count(DISTINCT expr[, expr_., expr_.])返回记录条数。
doublesum(col), sum(DISTINCT col)求和
doubleavg(col), avg(DISTINCT col)求平均值
doublemin(col)返回指定列中最小值
doublemax(col)返回指定列中最大值
doublevar_pop(col)返回指定列的方差
doublevar_samp(col)返回指定列的样本方差
doublestddev_pop(col)返回指定列的偏差
doublestddev_samp(col)返回指定列的样本偏差
doublecovar_pop(col1, col2)两列数值协方差
doublecovar_samp(col1, col2)两列数值样本协方差
doublecorr(col1, col2)返回两列数值的相关系数
doublepercentile(col, p)返回数值区域的百分比数值点。0<=P<=1,否则返回NULL,不支持浮点型数值。
arraypercentile(col, array(p~1,\ [, p,2,]…))返回数值区域的一组百分比值分别对应的数值点。0<=P<=1,否则返回NULL,不支持浮点型数值。
doublepercentile_approx(col, p[, B])Returns an approximate pth percentile of a numeric column (including floating point types) in the group. The B parameter controls approximation accuracy at the cost of memory. Higher values yield better approximations, and the default is 10,000. When the number of distinct values in col is smaller than B, this gives an exact percentile value.
arraypercentile_approx(col, array(p~1, [, p,2_]…) [, B])Same as above, but accepts and returns an array of percentile values instead of a single one.
array<struct{‘x’,'y’}>histogram_numeric(col, b)Computes a histogram of a numeric column in the group using b non-uniformly spaced bins. The output is an array of size b of double-valued (x,y) coordinates that represent the bin centers and heights
arraycollect_set(col)返回无重复记录

explode

  1. explode 命令可以将行数据,按指定规则切分出多行
  2. 用explode做行切分,注意表里只有一列,并且行数据是string类型,因为只有字符类型才能做切分

原始数据:
100,200,300
200,300,500
要求:
要将上面两行数据根据逗号拆分成多行(每个数字占一行)
实现步骤
1. 上传HDFS,并创建对应的外部表,执行:create external table ex1 (num string) location ‘/ex’;
2. 通过explode指令来做行切分,执行:select explode(split(num,’,’)) from ex1;

在这里插入图片描述

元数据

  1. 在Hive中,库名,表名,字段名,分区,分桶,索引,视图等信息属于元数据库
  2. Hive将元数据放在了关系型数据库中,如果不指定,那么默认使用Hive自带的Derby(单连接数据库)。Hive中的元数据只支持Derby和Mysql.

UDF

user define function

  1. 如果HIve中提供的函数不够用的时候,就需要自定义函数
  2. 自定义一个类继承UDF,然后写evaluate方法
package com.yasuofenglei;

import org.apache.hadoop.hive.ql.exec.UDF;

//从字符串中提取数字
/*
自定义hive函数
 */
public class Getint extends UDF {

    public int evaluate(String str){
        str =str.replaceAll("\\D", "");
        return Integer.parseInt(str);
    }
}

在hive中执行

add jar /myjar/udf.jar;
create temporary function getint as 'com.yasuofenglei.Getint';;
select getint("a1b2");

hive 使用mysql

mysql权限

grant all privileges on *.* to 'root'@'hadoop01' identified by 'root' with grant option;
flush privileges;
create database hive character set latin1;

mysql配置:vim /usr/my.cnf

[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
character_set_server=utf8
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
binlog_format=mixed

修改配置后重启mysql服务

service mysql restart

hive/conf/hive-sit.xml

<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://hadoop01:3306/hive?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>root</value>
</property>
</configuration>

索引

创建索引表

create index score_index on table score(name) as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler' with deferred rebuild in table name_index;

建立索引

alter index score_index on score rebuild;

查询

hive> select * from name_index;
OK
Adair	hdfs://hadoop01:9000/score/score.txt	[61]
Alex	hdfs://hadoop01:9000/score/score.txt	[14]
Bob	hdfs://hadoop01:9000/score/score.txt	[0]
Chad	hdfs://hadoop01:9000/score/score.txt	[77]
Colin	hdfs://hadoop01:9000/score/score.txt	[92]
Eden	hdfs://hadoop01:9000/score/score.txt	[108]
Grace	hdfs://hadoop01:9000/score/score.txt	[29]
Grover	hdfs://hadoop01:9000/score/score.txt	[123]
Henry	hdfs://hadoop01:9000/score/score.txt	[45]

在Hive中,添加的数据不会自动建立索引,需要手动建立索引

Hive优化

  1. map side join

a. mapJoin的主要意思就是,当连接的两个表是一个比较小的表和一个特别大的表的时候,可以把比较小的table直接放到内存中去,然后再对比较大的表格进行map操作,此时join就发生在map操作的时候,每当扫描一个大的table中的数据,就要去去查看小表的数据,哪条与之相符,继而进行连接。这里的join并不会涉及reduce操作。map端join的优势就是在于没有shuffle,在实际的应用中,设置方式:set hive.auto.convert.join=true;
b. hive有一个参数:hive.mapjoin.smalltable.filesize,默认值是25mb(其中一个表大小小于25mb时,自动启用mapjoin)
c. 要求:在hive做join时,要求小表在前(左)

  1. join语句优化
    如果在join操作中出现了where查询,那么最好先用子查询执行where筛选条件,然后再进行join.
    优化前:select m.cid,u.id from order m join customer u on m.cid=u.id where m.dt=’20160801’;
    优化后:select m.cid,u.id from (select cid from order where dt=’20160801’)m join customer u on m.cid = u.id

  2. group by 优化
    调优参数:set hive.groupby.skewindata=true;
    数据倾斜时负载均衡,当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作
    由上面可以看出起到至关重要的作用的其实是第二个参数的设置,它使计算变成了两个mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个key 随机均匀分布到各个 reduce 上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上,所以需要第二次的mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜

  3. count distinct 优化
    优化前:select count(distinct id )from tablename
    优化后:select count(*) from (select distinct id from tablename)tmp;
    分析:
    a. 优化前
    i. 由于对id=引入了distinct操作,所以在Map阶段无法利用combine对输出结果去消重,必须将id作为key输出
    ii. 在reduce阶段再对来自于不同的MapTask的结果进行消重,计入最终统计值
    iii. 由于ReduceTask的数量默认为1,所以导致MapTask的所有结果都只能由这一个ReduceTask处理,这就使得ReduceTask的执行效率成为整个任务的瓶颈
    iv. 虽然在使用hive的时候可以通过set mapred.reduce.tasks设置ReduceTask的数量,但是Hive在处理COUNT这种“全聚合(full aggregates)”计算时,它会忽略用户指定的Reduce Task数,而强制使用1
    b. 优化后:
    i. 利用Hive对嵌套语句的支持,将原来一个MapReduce作业转换为两个作业:在第一阶段选出全部的非重复id,在第二阶段再对这些已消重的id进行计数
    ii. 在第一阶段我们可以通过增大Reduce的并发数,并发处理Map输出
    iii. 在第二阶段,由于id已经消重,因此COUNT(*)操作在Map阶段不需要输出原id数据,只输出一个合并后的计数即可。这样即使第二阶段Hive强制指定一个Reduce Task,极少量的Map输出数据也不会使单一的Reduce Task成为瓶颈
    iv. 这一优化使得在同样的运行环境下,优化后的语句执行只需要原语句20%左右的时间

    1. 调整切片数(map任务数)
      a. Hive底层自动对小文件做了优化,用了CombineTextInputFormat,将做个小文件切片合成一个切片。如果合成完之后的切片大小>mapred.max.split.size 的大小,就会生成一个新的切片
      b. mapred.max.split.size 默认是128MB,设置方式为:set mapred.max.split.size=134217728(128MB)
      c. 对于切片数(MapTask)数量的调整,要根据实际业务来定,比如一个100MB的文件包含了有1千万条数据,此时可以调成10个MapTask,则每个MapTask处理1百万条数据。

    2. JVM重利用
      a. 设置方式:set mapred.job.reuse.jvm.num.tasks=20(默认是1个)
      b. JVM重用是hadoop调优参数的内容,对hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景大多数执行时间都很短。这时JVM的启动过程可能会造成相当大的开销,尤其是执行的job包含有成千上万个task任务的情况
      c. JVM重用可以使得一个JVM进程在同一个JOB中重新使用N次后才会销毁。

    3. 启用严格模式
      a. 用户可以通过 set hive.mapred.mode=strict 来设置严格模式,改成unstrict则为非严格模式
      b. 在严格模式下,用户在运行如下query的时候会报错:
      i. 分区表的查询没有使用分区字段来限制
      ii. 使用了order by 但没有使用limit语句(如果不使用limit,会对查询结果进行全局排序,消耗时间长)
      iii. 产生了笛卡尔积

    4. 关闭推测执行机制
      通常在测试环境下机会确定应用程序是否跑通,如果还加上推测执行,那么在数据分片本来就会发生数据倾斜,执行执行时间就是比其他的时间长,那么hive就会把这个执行时间长的job当作运行失败,继而又产生一个相同的job去运行,造成资源的浪费。可通过如下设置关闭推测执行:
      set mapreduce.map.speculative=false
      set mapreduce.reduce.speculative=false
      set hive.mapred.reduce.tasks.speculative.execution=false

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值