Hive函数

文章目录

    • 一、Hive建表SQL
    • 二、Hive函数
    • 三、函数
      • 1、查看内置函数
      • 2、空字段赋值(nvl)
      • 3、CASE WHEN THEN ELSE END
      • 4、行转列
      • 5、列转行
      • 6、开窗函数
        • 6.1 简介
        • 6.2 语法
        • 6.3 案例
        • 6.4 LAG函数
        • 6.5 Ntile函数
        • 6.6 Rank
      • 7、自定义函数
    • 四、压缩和存储
      • 1、简介
      • 2、压缩简介
      • 3、Map输出阶段压缩
      • 4、开启Reduce输出阶段压缩
      • 5、文件存储格式
        • 5.1 列式存储和行式存储
        • 5.2 TextFile_行存储
        • 5.3 Orc_列存储
        • 5.4 Parquet_列存储
        • 5.5 数据存储大小对比
      • 6、存储和压缩结合
    • 四、企业级调优
      • 1、查看执行计划
      • 2、Hive建表优化
      • 3、HQL语法优化
        • 3.1 列裁剪和分区裁剪
        • 3.2 Group By
        • 3.3 CBO优化
      • 4、数据倾斜
        • 4.1 现象
        • 4.2 单表数据倾斜优化
        • 4.3 Join数据倾斜优化
      • 5、Hive Job优化

一、Hive建表SQL

Hive建表SQL

二、Hive函数

Hive函数

三、函数

1、查看内置函数

查看系统自带函数

show functions;

查看自带函数用法

#	显示简单用法
desc function !=;
# 显示详细用法
desc function extended !=;

2、空字段赋值(nvl)

NVL:给值为NULL的数据赋值,它的格式是NVL( value,default_value)。
功能:如果value为NULL,则NVL函数返回default_value的值,否则返回value的值如果两个参数都为NULL ,则返回NULL。
#	当common为空时,返回age
SELECT nvl(name,'age') FROM user;
#	当name为空时候,用full_name替代
SELECT nvl(name,full_name) FROM user;

3、CASE WHEN THEN ELSE END

根据不同数据,返回不同逻辑

SELECTCASE deptnoWHEN 1 THEN EngineeringWHEN 2 THEN FinanceELSE adminEND,CASE zoneWHEN 7 THEN AmericasELSE Asia-PacENDFROM emp_details/** 当a=b时,返回c;当a=d时,返回d;当a=e时,放回e;其他情况返回f。*/
CASE a WHEN b THEN cWHEN d THEN eELSE f
END

案例:

SELECT name,CASE sex WHEN '男' THEN 1 ELSE 0 END
FROM default.user01 uSELECT name,SUM(CASE sex WHEN '男'THEN  1 ELSE 0 END )
FROM default.user01 u 
GROUP BY name ;

4、行转列

将多行数据进行汇总成1条数据、多行转为单行

  • CONCAT(string A/col, string B/col…):多个字段拼接
  • CONCAT_WS(separator, str1, str2,...):多字段拼接(指定拼接符号)
  • COLLECT_SET(col):接受分组数据,汇总为Array(去重)
  • COLLECT_LIST(col):接受分组数据,汇总为Array(不去重)
SELECT deptno AS Deptno,CONCAT_WS(',' , COLLECT_LIST(Ename))   AS enames
FROM user
GROUP BY deptno

在这里插入图片描述

CONCAT

# 字符串拼接
#	返回输入字符串连接后的结果,支持任意个输入字符串;
CONCAT(string A/col, string B/col…):

案例:

SELECT CONCAT(name,age)  FROM  default.user01 u ;
#	结果:
悟空12
大海14

**CONCAT_WS(separator, str1, str2,...):**多字符串拼接

  • 它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。

  • 分隔符可以是与剩余参数一样的字符串。

  • 如果分隔符是 NULL,返回值也将为 NULL。

  • 这个函数会跳过分隔符参数后的任何 NULL 和空字符串。

  • 分隔符将被加到被连接的字符串之间;

  • 注意: CONCAT_WS must be "string or array<string>

#	`separator`:连接符
#	`str1`:参数1
#	`str2`:参数2
#	:字符串拼接(CONCAT_WS('+','a','b')=>a+b)
CONCAT_WS(separator, str1, str2,...)

案例:

SELECT concat_ws('.', 'www', 'facebook', 'com') FROM default.user01;
www.facebook.comSELECT concat_ws('.', 'www', array('facebook', 'com')) FROM default.user01;
www.facebook.com
www.facebook.com

COLLECT_SET(col)

  • 函数只接受基本数据类型
  • 它的主要作用是将某字段的值进行去重汇总,产生array类型字段。
  • 去重
#	将分组后数据汇总为Array
collect_list(name)

案例:

#	["宋宋","凤姐","婷婷"]
select collect_set(name)from default.user01 group by age;
#	宋宋+凤姐+婷婷
select  concat_ws('+',collect_set(name))from default.user01 group by age;

COLLECT_LIST(col):

  • 不去重
  • 函数指接收基本数据类型
  • 它的主要作用是将某字段的值进行不去重汇总,产生array类型字段。
#	将分组后数据汇总为Array
collect_list(name)

案例

#	["宋宋","宋宋","凤姐","婷婷"]
select collect_list(name)from default.user01 group by age;
#	宋宋+宋宋+凤姐+婷婷
select  concat_ws('+',collect_list(name))from default.user01 group by age;

5、列转行

  • EXPLODE(col):将hive表的一列中复杂的array或者map结构拆分成多行。
  • SPLIT(string str, string regex): 按照regex字符串分割str,会返回分割后的字符串数组。
  • LATERAL VIEW:侧视图
    • LATERAL VIEW udtf(expression) tableAlias AS columnAlias
    • 用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。lateral view首先为原始表的每行调用UDTF,UDTF会报一行拆分成一行或者多行,lateral view再把结果组合,产生一个支持别名表的虚拟表。

在这里插入图片描述

在这里插入图片描述

SELECT split(category,",")  FROM movie_info ;

在这里插入图片描述

SELECT explode(split(category,","))  FROM movie_info mi;

在这里插入图片描述

  • split:将category列中数据,拆分为多条,以Array类型。
  • explode:将单列中Array存储的转为多行数据。
  • lateral VIEW:将Array中数据整合为可被查询的列。
SELECT movie,category_name FROM movie_info 
lateral VIEW
explode(split(category,",")) movie_info_tmp  AS category_name ;

6、开窗函数

6.1 简介
  • 窗口函数不同于我们熟悉的常规函数及聚合函数,它输入多行数据(一个窗口),为每行数据进行一次计算,返回一个值。
  • 灵活运用窗口函数可以解决很多复杂的问题,如去重、排名、同比及和环比、连续登录等。

在这里插入图片描述

6.2 语法

语法:

在这里插入图片描述

Function(arg1 ……) over([partition by arg1 ……] [order by arg1 ……] [<window_expression>])
  • rows必须跟在Order by 子句之后,对排序的结果进行限制,使用固定的行数来限制分区中的数据行数量

  • 如果不指定partition by,则不对数据进行分区,换句话说,所有数据看作同一个分区。

  • 如果不指定order by, 则不对各分区进行排序,通常用于那些顺序无关的窗口函数,如sum()。

  • 如果不指定窗口子句:

    • 不指定order by,默认使用分区内所有行,等同于
    Function() over(rows between unbounded precedeing and unbounded following)
    
    • 如果指定order by,默认使用分区内第起点到当前行,等同于
    Function() over(rows between unbounded preceding and current row)
    
  • Over()语法

语法解释(添加)解释(不添加)
Partition by:表示将数据先按字段进行分区不对数据进行分区,换句话说,所有数据看作同一个分区
Order by:表示将各个分区内的数据按字段进行排序。
不指定默认所有行。
则不对各分区进行排序,通常用于那些顺序无关的窗口函数。
指定后:从开头行至当前行。
partition by:
不指定:则不对数据进行分区,换句话说,所有数据看作同一个分区。order by:
不指定order by:默认使用分区内所有行,等同于
指定order by:  默认使用分区内第起点到当前行,等同于
  • window_expression语法
语法解释
n preceding往前n行
n following往后n行
current row当前行
unbounded preceding从前面的起点开始
unbounded following到后面的终点结束
#   从开头到当前行
ROWS BETWEEN unbounded preceding AND current row#   昨天至今天
rows between 1 preceding and current row#   当天到最后一天
rows between current row and unbounded following
6.3 案例

数据表

  • 查询在2017年4月份,到店购买的人,及到店次数
selectname ,count(name) over()
frombusiness
wheresubstring(orderdate, 1, 7)= '2017-04'
group by name;
  • 查询顾客的购买明细,及到当前日期为止的购买总金额
selectname,orderdate,cost,sum(cost)over(partition by name
order byorderdate)
from business;

执行结果

jack	2017-01-01	10	10
jack	2017-01-05	46	56
jack	2017-01-08	55	111
jack	2017-02-03	23	134
jack	2017-04-06	42	176
mart	2017-04-08	62	62
  • 每一行数据都新增一列,即消费总额
selectname,orderdate,cost,sum(cost) over() sample1
from business;

执行结果:

mart	2017-04-13	94	661
neil	2017-06-12	80	661
mart	2017-04-11	75	661
neil	2017-05-10	12	661
mart	2017-04-09	68	661
mart	2017-04-08	62	661
jack	2017-01-08	55	661
  • 计算每个人的销售总额
    • 以name分区计算,每行数据新增一列,即每人消费总额
selectname,orderdate,cost ,sum(cost)over(partition by name)
from business;

执行结果:

jack	2017-01-05	46	176
jack	2017-01-08	55	176
jack	2017-01-01	10	176
jack	2017-04-06	42	176
jack	2017-02-03	23	176
mart	2017-04-13	94	299
mart	2017-04-11	75	299
mart	2017-04-09	68	299
  • 计算每个人截止到当天的销售总额
    • 以name分区、日期排序计算,每行数据增一列,即截止到当前的消费总额,也就是从起点到当前行做聚合。
    • 如果指定order by,默认使用分区内第起点到当前行。
selectname,orderdate,cost,sum(cost)over(partition by name order by orderdate)as sum_now
frombusiness;
selectname,orderdate,cost,sum(cost)over(partition by name order by orderdate 
# 	固定写法,表明从开头到当前行rows between unbounded preceding and current row )as sum_now
frombusiness;

执行结果:

jack	2017-01-01	10	10
jack	2017-01-05	46	56
jack	2017-01-08	55	111
jack	2017-02-03	23	134
jack	2017-04-06	42	176
mart	2017-04-08	62	62
mart	2017-04-09	68	130
  • 每个人连续两天的消费总额
    • 以name分区、日期排序计算,每行数据增一列,即连续两天的消费总额也就是前一行和当前行聚合。
    • 当天的值,为当天值与昨天值相加。
select name,orderdate,cost, sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING and current row ) as sample5
from business;

执行结果

jack	2017-01-01	10	10
jack	2017-01-05	46	56   (10+46=56)
jack	2017-01-08	55	101  (46+55=101)
jack	2017-02-03	23	78		(55+23=78)
jack	2017-04-06	42	65
mart	2017-04-08	62	62
mart	2017-04-09	68	130
  • 每个人从当天到最后一天的消费总额
    • 以name分区、日期排序计算,每行数据增一列,即当前天到最后一天的消费总额,也就是当前行聚合最后一行。
    • 行,从当前行至最后一行总和。
select name,orderdate,cost,sum(cost) over(partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING )
from business;

计算结果:

jack	2017-01-01	10	176
jack	2017-01-05	46	166
jack	2017-01-08	55	120	(120=42+23+55)
jack	2017-02-03	23	65	(65=42+23)
jack	2017-04-06	42	42	(42=42)
mart	2017-04-08	62	299
mart	2017-04-09	68	237
6.4 LAG函数
  • Lag函数用于统计窗口内往上第n行值。
  • scalar_pexpression:列名。
  • offset :为往上几行。
  • default :是设置的默认值(当往上第n行为NULL时,取默认值,否则就为NULL)
LAG  (scalar_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause);
  • 查看顾客上次的购买时间
selectname,orderdate,cost,lag(orderdate,1,'1900-01-01') over(partition by name order by	orderdate ) as last_time
from	business ;

执行结果:

jack	2017-01-01	10	1900-01-01
jack	2017-01-05	46	2017-01-01
jack	2017-01-08	55	2017-01-05
jack	2017-02-03	23	2017-01-08
jack	2017-04-06	42	2017-02-03
mart	2017-04-08	62	1900-01-01
mart	2017-04-09	68	2017-04-08
mart	2017-04-11	75	2017-04-09
6.5 Ntile函数
  • 为已排序的行,均分为指定数量的组,组号按顺序排列,返回组号,不支持rows between
selectname,orderdate,cost,ntile(5) over( order by orderdate) sorted
from business;

执行结果:(分为了5组,下面取第1组数据即可)

jack	2017-01-01	10	1
tony	2017-01-02	15	1
tony	2017-01-04	29	1
jack	2017-01-05	46	2
tony	2017-01-07	50	2
jack	2017-01-08	55	2
jack	2017-02-03	23	3
jack	2017-04-06	42	3
mart	2017-04-08	62	3
mart	2017-04-09	68	4
mart	2017-04-11	75	4
mart	2017-04-13	94	4
neil	2017-05-10	12	5
neil	2017-06-12	80	5

取第一组数据

selectt1.name,t1.orderdate,t1.cost
from(selectname,orderdate,cost,ntile(5) over( order by orderdate) sortedfrom business ) t1
wheret1.sorted = 1;

执行结果:

OK
jack	2017-01-01	10
tony	2017-01-02	15
tony	2017-01-04	29
6.6 Rank
  • Rank():排序,值相同时会重复,总数不会变(1、1、3、4)。
  • DENSE_RANK():排序,值相同时会重复,总数会较少(1、1、2、3)。
  • ROW_NUMBER():根据顺序计算。字段相同就按排头字段继续排(1、2、3、4)。

源数据:

在这里插入图片描述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

7、自定义函数

  • **内置函数:**Hive自带的函数。

  • **自定义函数:**当Hive提供的内置函数无法满足你的业务处理需要时。可以自己定义一些函数。

    • UDF(User-Defined-Function): 一进一出。

    • UDAF(User-Defined Aggregation Function):聚合函数,多进一出,类似:count/max/min

    • UDTF(User-Defined Table-Generating Functions):炸裂函数,一进多出,如:explode()

四、压缩和存储

1、简介

  • Hive不会强制要求将数据转换成特定的格式才能使用。利用Hadoop的InputFormat API可以从不同数据源读取数据,使用OutputFormat API可以将数据写成不同的格式输出。
  • 对数据进行压缩虽然会增加额外的CPU开销,但是会节约客观的磁盘空间,并且通过减少载入内存的数据量而提高I/O吞吐量会更加提高网络传输性能。
  • 原则上Hadoop的job时I/O密集型的话就可以采用压缩可以提高性能,如果job是CPU密集型的话,那么使用压缩可能会降低执行性能。

2、压缩简介

常用压缩算法

在这里插入图片描述

压缩格式算法文件扩展名是否可切分对应的编码/解码器
DeflateDeflate.deflateorg.apache.hadoop.io.compress.DefaultCodec
GzipDeflate.gzorg.apache.hadoop.io.compress.GzipCodec
Bzip2Bzip2.bz2org.apache.hadoop.io.compress.BZip2Codec
LzoLzo.lzocom.hadoop.compression.lzo.LzopCodec
SnappySnappy.snappyorg.apache.hadoop.io.compress.SnappyCodec

压缩效率对比

压缩算法原始文件大小压缩文件大小压缩速度解压速度
gzip8.3GB1.8GB17.5MB/s58MB/s
bzip28.3GB1.1GB2.4MB/s9.5MB/s
LZO8.3GB2.9GB49.3MB/s74.6MB/s

要在Hadoop中启用压缩,可以配置如下参数(mapred-site.xml文件中):

参数默认值阶段建议
io.compression.codecs (在core-site.xml中配置)org.apache.hadoop.io.compress.DefaultCodec, org.apache.hadoop.io.compress.GzipCodec, org.apache.hadoop.io.compress.BZip2Codec,
org.apache.hadoop.io.compress.Lz4Codec
输入压缩Hadoop使用文件扩展名判断是否支持某种编解码器
mapreduce.map.output.compressfalsemapper输出这个参数设为true启用压缩
mapreduce.map.output.compress.codecorg.apache.hadoop.io.compress.DefaultCodecmapper输出使用LZO、LZ4或snappy编解码器在此阶段压缩数据
mapreduce.output.fileoutputformat.compressfalsereducer输出这个参数设为true启用压缩
mapreduce.output.fileoutputformat.compress.codecorg.apache.hadoop.io.compress. DefaultCodecreducer输出使用标准工具或者编解码器,如gzip和bzip2
mapreduce.output.fileoutputformat.compress.typeRECORDreducer输出SequenceFile输出使用的压缩类型:NONE和BLOCK

3、Map输出阶段压缩

开启map输出阶段压缩可以减少job中map和Reduce task间数据传输量。

(1)开启hive中间传输数据压缩功能

set hive.exec.compress.intermediate =true;

(2)开启mapreduce中map输出压缩功能

set mapreduce.map.output.compress=true;

(3)设置mapreduce中map输出数据的压缩方式

set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;

(4)执行查询语句

select count(ename) name from emp;

查看历史日志中,有压缩方式.snappy

在这里插入图片描述

4、开启Reduce输出阶段压缩

当Hive将输出写入到表中时可以通过属性hive.exec.compress.output,对输出内容进行压缩。

hive.exec.compress.output = false,这样输出就是非压缩的纯文本文件了。

hive.exec.compress.output = true,来开启输出结果压缩功能。

(1)开启hive最终输出数据压缩功能

set hive.exec.compress.output=true;

(2)开启mapreduce最终输出数据压缩

set mapreduce.output.fileoutputformat.compress=true;

(3)设置mapreduce最终数据输出压缩方式

set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;

(4)设置mapreduce最终数据输出压缩为块压缩

set mapreduce.output.fileoutputformat.compress.type=BLOCK;

(5)测试一下输出结果是否是压缩文件

insert overwrite local directory '/opt/module/hive/datas/distribute-result' select * from score distribute by name sort by score desc;

在这里插入图片描述

5、文件存储格式

5.1 列式存储和行式存储

Hive支持的存储数据的格式主要有:

  • TEXTFILE:行存储
  • SEQUENCEFILE:行存储
  • ORC:列存储
  • PARQUET:列存储

如图所示左边为逻辑表,右边第一个为行式存储,第二个为列式存储。

在这里插入图片描述

  • 行存储的特点

查询满足条件的一整行数据的时候

列存储则需要去每个聚集的字段找到对应的每个列的值

行存储只需要找到其中一个值,其余的值都在相邻地方

所以此时行存储查询的速度更快。

  • 列存储的特点

每个字段的数据聚集存储,查询只需要少数几个字段的时候,能大大减少读取的数据量;

每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。

5.2 TextFile_行存储
  • 默认格式,数据不做压缩,磁盘开销大,数据解析开销大。
  • 可结合Gzip、Bzip2使用,但使用Gzip这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
5.3 Orc_列存储

Orc (Optimized Row Columnar)是Hive 0.11版里引入的新的存储格式。

在这里插入图片描述

如下图所示可以看到每个Orc文件由1个或多个stripe组成,每个stripe一般为HDFS的块大小,每一个stripe包含多条记录,这些记录按照列进行独立存储,对应到Parquet中的row group的概念。

  • 每个Stripe里有三部分组成,分别是Index Data,Row Data,Stripe Footer:

    • Index Data:一个轻量级的index,默认是每隔1W行做一个索引。这里做的索引应该只是记录某行的各字段在Row Data中的offset。

    • Row Data:存的是具体的数据,先取部分行,然后对这些行按列进行存储。对每个列进行了编码,分成多个Stream来存储。

    • Stripe Footer:存的是各个Stream的类型,长度等信息。每个文件有一个File Footer,这里面存的是每个Stripe的行数,每个Column的数据类型信息等;每个文件的尾部是一个PostScript,这里面记录了整个文件的压缩类型以及FileFooter的长度信息等。在读取文件时,会seek到文件尾部读PostScript,从里面解析到File Footer长度,再读FileFooter,从里面解析到各个Stripe信息,再读各个Stripe,即从后往前读。

ORC中压缩:

  • Zlib:压缩比高,效率低。压缩ORC的默认压缩格式。
  • Snappy:压缩比低,效率高。
5.4 Parquet_列存储

Parquet文件是以二进制方式存储的,所以是不可以直接读取的文件中包括该文件的数据和元数据,因此Parquet格式文件是自解析的。

  • (1)行组(Row Group):每一个行组包含一定的行数,在一个HDFS文件中至少存储一个行组,类似于orc的stripe的概念。
  • (2)列块(Column Chunk):在一个行组中每一列保存在一个列块中,行组中的所有列连续的存储在这个行组文件中。一个列块中的值都是相同类型的,不同的列块可能使用不同的算法进行压缩。
  • (3)页(Page):每一个列块划分为多个页,一个页是最小的编码的单位,在同一个列块的不同页可能使用不同的编码方式。

通常情况下,在存储Parquet数据的时候会按照Block大小设置行组的大小,由于一般情况下每一个Mapper任务处理数据的最小单位是一个Block,这样可以把每一个行组由一个Mapper任务处理,增大任务执行并行度。

在这里插入图片描述

上图展示了一个Parquet文件的内容,一个文件中可以存储多个行组,文件的首位都是该文件的Magic Code,用于校验它是否是一个Parquet文件,Footer length记录了文件元数据的大小,通过该值和文件长度可以计算出元数据的偏移量,文件的元数据中包括每一个行组的元数据信息和该文件存储数据的Schema信息。

除了文件中每一个行组的元数据,每一页的开始都会存储该页的元数据,在Parquet中,有三种类型的页:数据页、字典页和索引页。数据页用于存储当前行组中该列的值,字典页存储该列值的编码字典,每一个列块中最多包含一个字典页,索引页用来存储当前行组下该列的索引,目前Parquet中还不支持索引页。

5.5 数据存储大小对比
  • TextFile
create table log_text (track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string
)
row format delimited fields terminated by '\t'
stored as textfile;
  • ORC
create table log_orc(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="NONE"); // 由于ORC格式时自带压缩的,这设置orc存储不使用压缩
  • Parquet
create table log_parquet(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as parquet ;

同样数据文件存储后大小:

  • TextFile:18.1M
  • ORC:7.7 M
  • Parquet:13.1M

存储的大小对比:ORC > Parquet > textFile

查询速度:速度接近

6、存储和压缩结合

KeyDefaultNotes
orc.compressZLIBhigh level compression (one of NONE, ZLIB, SNAPPY)
orc.compress.size262,144number of bytes in each compression chunk
orc.stripe.size268,435,456number of bytes in each stripe
orc.row.index.stride10,000number of rows between index entries (must be >= 1000)
orc.create.indextruewhether to create row indexes
orc.bloom.filter.columns“”comma separated list of column names for which bloom filter should be created
orc.bloom.filter.fpp0.05false positive probability for bloom filter (must >0.0 and <1.0)

注意:所有关于ORCFile的参数都是在HQL语句的TBLPROPERTIES字段里面出现。

  • ZLIB压缩的ORC存储方式(2.8 M)
create table log_orc_zlib(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="ZLIB");
  • SNAPPY压缩的ORC存储方式(3.7 M)
create table log_orc_snappy(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="SNAPPY");
  • SNAPPY压缩的parquet存储方式(6.4 MB)
create table log_parquet_snappy(track_time string,url string,session_id string,referer string,ip string,end_user_id string,city_id string
)
row format delimited fields terminated by '\t'
stored as parquet
tblproperties("parquet.compression"="SNAPPY");
  • hive表的数据存储格式一般选择:orc或parquet。
  • 压缩方式一般选择snappy,lzo。
  • ORC默认压缩:Zlib

四、企业级调优

1、查看执行计划

EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query
  • 没有生成MR任务的
explain select * from emp;

在这里插入图片描述

  • 生成MR任务的
explain select deptno, avg(sal) avg_sal from emp group by deptno;

在这里插入图片描述

查看详细执行计划

explain extended select * from emp;

2、Hive建表优化

  • 分区表
  • 分桶表
  • 合适的文件格式

3、HQL语法优化

3.1 列裁剪和分区裁剪

在生产环境中,会面临列很多或者数据量很大时,如果使用select * 或者不指定分区进行全列或者全表扫描时效率很低。Hive在读取数据时,可以只读取查询中所需要的列,忽视其他的列,这样做可以节省读取开销(中间表存储开销和数据整合开销)

  • 列裁剪:在查询时只读取需要的列。
  • 分区裁剪:在查询中只读取需要的分区。
3.2 Group By
  • 默认情况下,Map阶段同一Key数据分给一个Reduce,当一个Key数据过大时就倾斜了。
  • 并不是所有的聚合操作都需要再Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。

在这里插入图片描述

参数配置

  • 开启Map端聚合设置
#	开启在Map端聚合
set hive.map.aggr = true
#	Map端聚合条目数目
set hive.groupby.mapaggr.checkinterval = 100000
#	开启数据倾斜时,进行负载均衡
set hive.groupby.skewindata = true
  • 当开启数据负载均衡时,生成的查询计划会有2个MRJob。

    第一个MRJob中,Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;

    第二个MRJob再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),最后完成最终的聚合操作。

3.3 CBO优化

4、数据倾斜

4.1 现象

数据倾斜:绝大多数任务很快完成,只有1个或者几个任务执行的很忙甚至最终执行失败。

数据过量:所有的任务执行都很慢。这时候只有提高执行资源才能优化HQL的执行效率。

原因:

按照Key分组后,少量的任务负载着绝大部分的数据的计算,也就是说。产生数据倾斜的HQL中一定存在着分组的操作,所以从HQL的角度,我们可以将数据倾斜分为单表携带了Group By字段的查询和2表(多表)Join的查询。

4.2 单表数据倾斜优化

1)使用参数优化

当任务中存在Group By操作同时聚合函数为count或者sum。可以设置参数来处理数据倾斜的问题。

#	是否在Map端进行聚合,默认为True
set hive.map.aggr = true
#	在Map端进行聚合操作的条目数目
set hive.groupby.mapaggr.checkinterval = 100000
#	有数据倾斜的时候进行负载均衡(默认是false)
set hive.groupby.skewindata = true

2)增加Reduce数量

当数据中多个key同时导致数据倾斜,可以通过增加Reduce的数量解决数据倾斜问题。

  • 方式一(动态调整):
#	每个Reduce处理的数据量默认为 256M(参数1)
set hive.exec.reducers.bytes.per.reducer=256000000
#	每个任务最大的Reduce数,默认为1009(参数2)
set hive.exec.reducers.max=1009
#	计算Reducer数的公式
N = min(参数2 ,总数入数据量/参数1)
  • 方式二(直接指定):
#	直接指定Reduce个数
set mapreduce.job.reduces = 15;
4.3 Join数据倾斜优化

1)使用参数

在编写Join查询语句时,如果确定是由于join出现的数据倾斜:

# join的键对应的记录条数超过这个值则会进行分拆,值根据具体数据量设置
set hive.skewjoin.key=100000;
# 如果是join过程出现倾斜应该设置为true
set hive.optimize.skewjoin=false;

如果开启了,在Join过程中Hive会将计数超过阈值hive.skewjoin.key(默认100000)的倾斜key对应的行临时写进文件中,然后再启动另一个job做map join生成结果。通过 hive.skewjoin.mapjoin.map.tasks参数还可以控制第二个job的mapper数量,默认10000。

set hive.skewjoin.mapjoin.map.tasks=10000;

2)大小表join

可以使用MapJoin,没有Reduce阶段就不会出现数据倾斜。

3)大表大表Join

使用打散加扩容的方式解决数据倾斜问题,选择其中较大的表做打算操作

SELECT * ,concat(id,'_' , '0 or 1 or 2')FROM A; t1

选择其中较小的表做扩容处理

SELECT *,concat(id,'-','0') from B
UNION ALL
SELECT *,concat(id,'-','1') from B
UNION ALL
SELECT *,concat(id,'-','2') from B;t2

5、Hive Job优化

1

1

1

1

1

1

1

1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/147025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

⑧【MySQL】数据库查询:内连接、外连接、自连接、子查询、多表查询

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 内连接、外连接、自连接、子查询、多表查询 ⑧…

使用Pandas进行时间重采样,充分挖掘数据价值

大家好&#xff0c;时间序列数据蕴含着很大价值&#xff0c;通过重采样技术可以提升原始数据的表现形式。本文将介绍数据重采样方法和工具&#xff0c;提升数据可视化技巧。 在进行时间数据可视化时&#xff0c;数据重采样是至关重要且非常有用的&#xff0c;它支持控制数据的…

ControlNet原理及应用

《Adding Conditional Control to Text-to-Image Diffusion Models》 目录 1.背景介绍 2.原理详解 2.1 Controlnet 2.2 用于Stable Diffusion的ControlNet 2.3 训练 2.4 推理 3.实验结果 3.1 定性结果 3.2 消融实验 3.3 和之前结果比较 3.4 数据集大小的影响 4.结…

Vite 启动默认只能访问localhost解决方法

事情的经过是因为我需要测试本地项目的接口,然后因为burp默认不抓取localhost,127.0.0.1 .而且我也不想去修改burp. 所以我通过本地IP地址访问项目, 发现项目无法访问。 默认启动 所以特此记录一下。 在本地项目的package.json 中需要运行的脚本后 添加 --host即可。 具体如下…

rabbitMQ的扇出模式(fanout发布订阅)的生产者与消费者使用案例

扇出模式 fanout 发布订阅模式 生产者 生产者发送消息到交换机&#xff08;logs&#xff09;,控制台输入消息作为生产者的消息发送 package com.esint.rabbitmq.work03;import com.esint.rabbitmq.RabbitMQUtils; import com.rabbitmq.client.Channel;import java.util.Scanne…

使用FP8加速PyTorch训练

现代的人工智能硬件架构(例如&#xff0c;Nvidia Hopper, Nvidia Ada Lovelace和Habana Gaudi2)中&#xff0c;FP8张量内核能够显著提高每秒浮点运算(FLOPS)&#xff0c;以及为人工智能训练和推理工作负载提供内存优化和节能的机会。 在这篇文章中&#xff0c;我们将介绍如何修…

Arduino驱动LM35线性温度传感器(温湿度传感器)

目录 1、传感器特性 2、控制器和传感器连线图 3、驱动程序 LM35半导体的温度传感器,可以用来对环境温度进行定性的检测。LM35半导体温度传感器是美国国家半导体公司生产的线性温度传感器。其测温范围是-40℃到150℃,灵敏度为10mV/℃,输出电压与温度成正比。

<C++> 反向迭代器

我们知道正向迭代器的设计&#xff1a;begin迭代器指向第一个数据&#xff0c;end迭代器指向最后一个数据的下一个位置 。移向下一个数据&#xff0c;解引用得到数据的值&#xff0c;并根据容器储存方式的不同&#xff0c;容器有不同类型的迭代器。 注意&#xff1a;rbegin迭代…

c语言:模拟实现qsort函数

qsort函数的功能&#xff1a; qsort相较于冒泡排序法&#xff0c;不仅效率更快&#xff0c;而且能够比较不同类型的元素&#xff0c;如&#xff1a;浮点数&#xff0c;结构体等等。这里我们来模拟下qsort是如何实现这一功能的&#xff0c;方便我们对指针数组有一个更深层次的理…

龙芯 操作系统选择和安装

龙芯3a5000及之后的cpu底层架构已经从mips64el改为了loongarch64 所以这里分了2种来说明&#xff0c;分别对应3a4000之前的和3a5000之后的 龙芯的系统安装难点在于操作系统的选取和引导 一、烧录工具 制作安装盘使用常规的烧录工具是不行滴&#xff0c;会提示没有\boot\initrd…

产品经理必备技能:如何快速锁定种子用户群体?

大家好&#xff0c;我是小米&#xff0c;一名热爱技术、热衷分享的90后小青年。今天我们要探讨的话题是一个在产品经理面试中经常被问到的问题&#xff1a;“产品上线后的种子用户该如何获取&#xff1f;”作为一个热爱挑战、乐于探讨的小伙伴&#xff0c;我将和大家分享一些我…

第七部分:Maven(项目管理工具)

目录 Maven简介 7.1&#xff1a;为什么学习Maven&#xff1f; 7.1.1、Maven是一个依赖管理工具 7.1.2&#xff1a;Maven是一个构建工具 7.1.3&#xff1a;结论 7.2&#xff1a;Maven介绍 7.3&#xff1a;Maven的优点 Maven安装和配置 7.4&#xff1a;安装教程及环境配置 …

最大似然估计的介绍

最大似然估计&#xff08;Maximum Likelihood Estimation&#xff0c;简称MLE&#xff09;是一种用于估计概率分布中参数的方法。该方法的核心思想是选择使得观察到的数据在给定模型下出现的概率最大的参数值作为估计值。 最大似然估计具有很好的性质&#xff0c;包括渐进正态性…

SystemVerilog学习 (9)——随机化

目录 一、概述 二、随机化 2.1、如何简单地产生一个随机数 2.1.1 利用系统函数产生随机数 2.1.2 urandom() 2.2、什么需要随机化 2.3、随机约束 2.3.1 rand 和 randc 2.3.2 随机约束的使用 2.3.3 约束块 三、总结 一、概述 随着设计变得越来越大,要产生一个完整的激…

面试资料快速复习 Git常用命令(简单实用)

Git-command Git常用命令、面试复习、简单实用命令 ​ 一、概念理解 &#xff08;一&#xff09;工作区、暂存区、本地仓库、远程仓库 workspace&#xff1a;工作区staging area&#xff1a;暂存区/缓存区local repository&#xff1a;本地仓库remote repository&#xff…

Apache Airflow (九) :Airflow Operators及案例之BashOperator及调度Shell命令及脚本

&#x1f3e1; 个人主页&#xff1a;IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;加入大数据技术讨论群聊&#xff0c;获取更多大数据资料。 &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你大数据的个人空间-豹…

C#单例模式懒汉式与饿汉式

单例模式一般分为懒汉模式和饿汉模式&#xff0c;懒汉式单例在第一次引用时创建实例&#xff0c;不是在类加载时&#xff1b;饿汉式单例模式是一种在类加载时就创建实例的方式&#xff0c;因此也称为静态初始化。 单例模式实现的技巧时构造私有&#xff0c;向外提供静态实例。…

12-2- DCGAN -简单网络-卷积网络

功能 随机噪声→生成器→MINIST图像。 训练方法 0 损失函数:gan的优化目标是一个对抗损失,是二分类问题,用BCELoss 1 判别器的训练,首先固定生成器参数不变,其次判别器应当将真实图像判别为1,生成图像判别为0 loss=loss(real_out, 1)+loss(fake_out, 0) 2 生成器的…

react-router-dom 版本6.18.0中NavLink的api和属性介绍

React Router 是一个基于 React 的路由库&#xff0c;它可以帮助我们在 React 应用中实现页面的切换和路由的管理。而 NavLink 则是 React Router 中的一个组件&#xff0c;它可以帮助我们实现导航栏的样式设置和路由跳转。 在 React Router 版本6.18.0 中&#xff0c;NavLink…

Matalab插值详解和源码

转载&#xff1a;Matalab插值详解和源码 - 知乎 (zhihu.com) 插值法 插值法又称“内插法”&#xff0c;是利用函数f (x)在某区间中已知的若干点的函数值&#xff0c;作出适当的特定函数&#xff0c;在区间的其他点上用这特定函数的值作为函数f (x)的近似值&#xff0c;这种方…