最近有重新回看了《Hadoop权威指南》,又想起来总结一些博文了,所以针对Hive常用函数和性能调优又仔细查了很多资料,写了这篇文章,还是一样,感谢各位在网络上的分享!!!
一.Hive常用函数
1.时间处理函数
函数名称 | 返回值 | 作用 | 备注 |
current_date() | string | 返回当天时间 | 返回时间格式‘yyyy-MM-dd’ |
unix_timestamp() | bigint | 返回当前时区的时间戳 | |
from_unixtime(bigint unixtime[, string format]) | string | 返回Unix时间戳转日期格式 | 可以通过format定义返回结果样式 |
unix_timestamp(string date,string pattern) | bigint | 返回制定格式转化至时间戳 | 转化失败返回0 |
to_date(string date) | string | 返回时间字段中的日期部分 | 格式错误返回null |
year(string date) | int | 返回时间字段中的‘年’部分 | month,day,hour,minute,second使用方法相同 |
datediff(string enddate,string startdate) | int | 返回(结束日期-开始日期)的数值 | 仅返回时间上的天数差距 |
2.类型转换函数
隐式类型转换:所有整数类型都可以隐式转换为一个范围更广的类型。所有整数类型 + float + String都可以转换为Double类型。时间戳和日期可以隐式地转换成文本类型。BOOLEAN不能做任何的类型转换。
显式类型转换:
cast( 表达式a as 数据类型b ):可以将表达式a的数据类型显式的转化为数据类型b,并且转化失败会返回null。
3.条件判断函数
函数名称 | 返回值 | 作用 | 备注 |
if(boolean condition, T valueTrue, T valueFalse) | T | 判断condition的正误 正确则返回valueTrue,错误则返回valueFalse | |
coalesce(T value1,T value2,...) | T | 返回参数列表中第一个非空数值 | 如果所有数值均为null,则返回null |
case when conditionA then answerB else answerC end | T | 如果conditionA成立,则返回answerB否则返回answerC | 可以连续 [when a then b] 对多种情况进行判断和结果返回 |
4.空值判断函数
hive表中默认将null存储为\N。可以使用is null和is not null来判断某值是否是空值。可以结合条件判断函数使用( if( valueA is null ,'true' , 'false' ) )。
也可以直接使用nvl()函数对数值列进行处理,同理还可以使用条件判断函数中的coalesce()函数。
nvl( 表达式a , 表达式b ):判断表达式a是否为null,若是则返回表达b,若不是则返回表达式a。等价于 if( 表达式a is null ,表达式b , 表达式a ) 。
if函数和nvl函数的区别:两者的区别在于if函数的参数值类型可以不同,但是nvl函数的参数类型必须为同类型。
在处理空字符串 '' 时,可以使用 a = '' 或者 a <> ''进行判断。
5.字符串处理函数
函数名称 | 返回值 | 作用 | 备注 |
length(string a) | int | 返回字符串a的长度 | |
reverse(string a) | string | 返回字符串a的字符串结果翻转 | |
concat(string a, string b,…) | string | 返回字符串a和字符串b和...的字符串拼接结果 | |
concat_ws(string sepString, string a, string b,…) | string | 返回字符串a和字符串b和...的字符串拼接结果,且字符串之间使用sepString连接 | |
substr(string a,int start[,int end]) | string | 返回字符串a从start位置开始到末尾【到end】截取出来的字符串 | |
upper(string a)/ucase(string a) | string | 返回字符串a的大写格式 | lower(string a)和lcase(string a)返回字符串a的小写格式 |
trim(string a) | string | 返回字符串a去除前后两端空格的字符串 | ltrim(string a)和rtrim(string a)单独去除左端/右端空格 |
regexp_replace(string a, string pattern, string b) | string | 将字符串a中符合正则表达式字符串pattern的内容替换为字符串b的内容 | 正则表达式pattern字符串需要注意转义 |
regexp_extract(string a, string pattern, int index) | string | 将字符串a按照正则表达式字符串pattern的内容拆分,并且返回下标为index的内容 | 类似于replace()函数中的小括号和$取值的方式,下标0为原始字符串 |
split(string a, string b) | array | 将字符串a按照字符串b进行分割,返回字符串数组 | 注意转义 |
instr(string a, string b) | int | 若字符串b在字符串a中存在则返回具体位置(int),不存在则返回0 | |
parse_url(string a, string partUrl[, string key]) | string | 解析url字符串a,并且根据具体所需partUrl返回对应位置数据信息。也可通过使用‘QUERY’和具体的key返回指定的参数数值 | partUrl可使用的参数包括: [HOST(域名),PATH(路径),QUERY(参数),REF(定位), PROTOCOL(协议)FILE(路径+参数),AUTHORITY(域名),USERINFO] |
parse_url_tuple(string a, string partUrl[, string key]) | string | 解析url字符串a,用法与parse_url类似,可以同时返回多个key的value值 | |
get_json_object(string a string path) | string | 解析json字符串a,并且根据path获取json字符串中对应key的value值 | 字符串a必须符合json格式,若字符串无效则返回null |
json_tuple(string a, string keyValue,...) | string | 解析json字符串a,并且根据keyValue取得对应key的value值 | get_json_object可以处理更加复杂的json,json_tuple可以处理一次想取出多个key的场景 |
lpad(string a, int len, string b) | string | 将字符串a左侧用字符串b补全至长度为len | rpad(string a, int len, string b)作用于右侧 |
find_in_set(string a, string strList) | int | 返回字符串a在strList中出现的位置(strList必须是用逗号分隔的字符串) | 如果没有找到对应字符,则返回0 |
6.其他类型处理函数
函数名称 | 返回值 | 作用 | 备注 |
explode() | | 用于array类型数据时,array中每个元素生成一行 用于map类型数据时,map中每个键值对一行,key/value各自一列 | 不能关联原有的表中的其他字段。不能与group by、cluster by、distribute by、sort by联用。不能进行UDTF嵌套。不允许选择其他表达式。 |
array_contains(array, T b) | T/F | 用于判断array类型数据中是否存在T类型的b | 可用于where条件查询语句 |
lateral view explode(array) | | 用于将单行array类型数据拆分为分开的多行数据结果集 array位置为想拆分的数组字段,单独拆分一列,相当于是该列产生的结果集与原表进行笛卡尔积,也可以同时拆分多列 | |
collect_list(arrayName) | | 将分组中的某列转为一个数组返回,不去重 | |
collect_set(arrayName) | | 将分组中的某列转为一个数组返回,去重 | |
7.分析窗口函数
用于分区排序( over( partition by ) ),动态group by,计算topN( row_number() )等场景。
定义window子句(eg. : rows between current row and 2 preceding),如果不指定ROWS BETWEEN,默认是从起点到当前行:
2 PRECEDING:前两行
2 FOLLOWING:后两行
CURRENT ROW:当前行
UNBOUNDED:起点
UNBOUNDED PRECEDING:从前面的起点
UNBOUNDED FOLLOWING:从后边的终点
函数名称 | 返回值 | 作用 | 备注 |
rank() | 序列函数 | 并列跳跃排名:在返回排名结果字段中并列名次的下一名将为并列数量+并列名次(如并列第一两名,则排行为1,1,3) 不支持window子句 | |
dense_rank() | 序列函数 | 并列不跳跃排名:在返回排名结果字段中并列名次的下一名将为正常名次(如并列第一两名,则排行为1,1,2) 不支持window子句 | |
row_number() | 序列函数 | 顺序排序:在返回排名结果字段中无视并列名次(如并列第一两名,则排行为1,2,3) 不支持window子句 | |
first_value() | 取值函数 | 返回当前排序分组内第一个数据的值(也可通过改变排序次序获取最大值或最小值) | |
last_value() | 取值函数 | 返回当前排序分组内最后一个数据的值(也可通过改变排序次序获取最大值或最小值) | |
ntile(int a) | 序列函数 | 将返回结果分为a份,可用于取百分比数量数据 | |
lag(string lineName[, int a]) | 上提函数 | 用于统计窗口内往上第n行值 第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL) | |
lead(string lineName[, int a]) | 下沉函数 | 作用同上,往下第n行值,其余相同 | |
cume_dist() | 序列函数 | 用于统计指定值占总数的百分比 | |
二.Hive性能调优
1.Hive配置调优(https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties)
所有黑体+下划线一般都不会选择默认值,用于调优,而所有正常字体一般可选择默认值。
配置语句 | 默认值 | 配置作用 | 备注 |
hive.auto.convert.join | false | 是否启用Hive基于输入文件大小的,将普通join转换为mapjoin的优化 MapJoin是常用的优化操作,适用于小表JOIN大表的场景,由于表的JOIN操作是在Map端且在内存进行的,所以其并不需要启动Reduce任务也就不需要经过shuffle阶段,从而能在一定程度上节省资源提高JOIN效率 | 该参数为true时,Hive自动对左边的表统计量,如果是小表就加入内存,即对小表使用mapjoin |
hive.mapjoin.smalltable.filesize | 25000000 | 小表的输入文件大小的阈值(单位:字节);如果文件大小小于此阈值,它将尝试将普通join转换为mapjoin | 该参数作为大表,小表判断的阈值,如果表的大小小于该值则会被加载到内存中运行 |
hive.auto.convert.join.noconditionaltask | true | 是否启用Hive基于输入文件大小的,将普通join转换为mapjoin的优化 | 将普通join转换为mapjoin时,是否将多个mapjoin转换为一个mapjoin |
hive.auto.convert.join.noconditionaltask.size | 10000000 | 将普通join转换为mapjoin时,最多可以将最大值为多少的小表转换为一个mapjoin | 多个mapjoin转换为1个时,所有小表的文件大小总和的最大值 |
hive.exec.parallel | false | 是否并行执行jobs,适用于可以并行执行的MapReduce job | |
hive.exec.parallel.thread.number | 8 | 设定最多可以并行执行多少个job | 代表一次 SQL 计算中允许并行执行的 job 个数的最大值 |
hive.execution.engine | mr(2.0.0后弃用) | 选择执行引擎。可选项有MapReduce,Tez和Spark | 当执行引擎发生改变时,可以通过对对应引擎进行调优达到对hive语句执行的优化 |
mapred.reduce.tasks | -1 | 默认每一个job对应的reducer的数量,通常设定为可用主机的近似值 | |
hive.exec.reducers.bytes.per.reducer | 256000000 | 每一个reducer处理的数据量大小 | |
hive.exec.reducers.max | 1009 | 每一个job最大可以使用的reducer数量 | |
hive.map.aggr | true | 在使用group by查询语句时,是否使用map端聚合 | |
hive.groupby.mapaggr.checkinterval | 100000 | 在map端group by聚合时处理的数据行数 | |
hive.map.aggr.hash.min.reduction=0.5; | 0.5 | 进行聚合的最小比例,如果聚合后数据量和处理的数据行数的比值大于该数字,则将关闭聚合。设置为1可以确保从未关闭聚合 | |
hive.map.aggr.hash.percentmemory | 0.3 | 当使用map端group by聚合时,map端聚合可使用的内存上限 | |
hive.groupby.skewindata | false | 在使用group by时是否进行数据倾斜优化 | |
2.Hive语句调优
(1).在表连接时将小表放在前边,大表放在后边。Hive会采取将小表都放在内存中,而后扫描大表的方式。
(2).慎重使用COUNT(DISTINCT col),distinct会将数据保存在内存中,加快速度,但是可能会发生OOM,可以通过使用ROW_NUMBER() OVER(PARTITION BY col)等方式替代。
(3).尽量不使用select *而是使用具体字段进行查询操作。
(4).尽量采取谓词下推(将数据过滤表达式尽可能的移动至靠近数据源的位置,以便尽可能早的处理表达式语句和尽可能少的处理无关数据)的方式书写语句。
(5).尽可能不使用order by语句或在使用order by语句时同limit语句一齐使用,否则可能会导致只有一个reducer运行的结果。