Apache Hive
-
json数据的解析
-
内置函数
-
get_json_object 一次可以解析出一个json值
-
json_tuple 可以解析出多个
-
扩展:如果是json数组呢?
- 思路:想法把json数组转换成为array 交给explode来炸开 结合 json_tuple 来使用
regexp_replace('json数组', '\\}\\,\\{','\\}\\;\\{') --把json数组中的分隔符替换成为; regexp_replace('asdas','[|]','') -- |表示or 把json中的[或者]替换成为空
-
-
-
窗口函数 分析函数
-
格式:带有over语句的函数
over (partition by xxx order by asc|desc) partition by用于指定根据表中哪个字段进行分 相同的分在一起 order by用于指定相同分区内根据谁进行排序 默认是正序(升序)
-
普通聚合函数和窗口函数的配合
-
格式
sum() avg() max() over(partition by xxx order by asc|desc)
-
默认是计算从第一行到当前行的操作 在这当中进行聚合操作
-
还支持window 子句 rows between 用于指定行的范围
-
如果不加order by asc|desc 只有partition by xxx 这时候聚合分区内所有的数据
-
-
row_number 、rank、dense_rank、ntile
- 适用于求分组topN问题 和分组几分之几的问题
-
hive的数据压缩
-
压缩的优缺点
- 优点:减少带宽 减少磁盘空间
- 缺点:浪费时间 增加cpu处理压力
-
压缩方式
- hive中间结果压缩(map输出的压缩)
- hive的最终结果压缩(reduce输出的压缩)
-
压缩算法选择
- 推荐:snappy
-
栗子:
--没有开启压缩 create table student_no_compress(Sno int,Sname string,Sex string,Sage int,Sdept string) row format delimited fields terminated by ','; insert into table student_no_compress select * from student; --开启压缩 create table student_compress(Sno int,Sname string,Sex string,Sage int,Sdept string) row format delimited fields terminated by ','; --首先开启map压缩功能 0: jdbc:hive2://node-1:10000> set hive.exec.compress.intermediate=true; No rows affected (0.004 seconds) 0: jdbc:hive2://node-1:10000> set mapreduce.map.output.compress=true; No rows affected (0.004 seconds) 0: jdbc:hive2://node-1:10000> set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec; --然后开启reduce压缩功能 0: jdbc:hive2://node-1:10000> set hive.exec.compress.output=true; No rows affected (0.006 seconds) 0: jdbc:hive2://node-1:10000> set mapreduce.output.fileoutputformat.compress=true; No rows affected (0.005 seconds) 0: jdbc:hive2://node-1:10000> set mapreduce.output.fileoutputformat.compress.codec =org.apache.hadoop.io.compress.SnappyCodec; No rows affected (0.003 seconds) 0: jdbc:hive2://node-1:10000> set mapreduce.output.fileoutputformat.compress.type=BLOCK; insert into table student_compress select * from student;
-
注意:snappy压缩的文件 属于二进制格式数据 不可以直接观察 hive在操作的时候可以自解析。
hive的存储格式
-
语法
create table stored as file-foramat
-
说明:
- 如果不指定语法 默认hive使用textfile格式存储 普通文本文件 行存储
- 此外还支持其他的文件存储格式:ORC Parquet格式
- ORC Parquet格式属于二进制格式的文件 不可以直接观察 hive可以自解析
- 文件存储格式结合数据压缩 可以带来更加棒棒的体验
-
文件存储格式对比
-
存储空间效果
orc > parquet >textfile
-
-
注意事项
- ORC格式文件和PARQUET格式文件都不能通过直接load加载的方式从普通text文件转成。
- 必须通过insert+select方式 底层通过mr程序把普通文件格式转化成orc等格式。
- 企业中要想把一批普通文本文件变成orc等二进制格式存储 首先存储成普通文件 然后通过insert+select得到
- 如果已经是orc等格式文件存储格式 直接load即可
hive 调优
-
fetch抓取
-
能不使用mr程序处理数据的,尽量不使用。
-
默认实现:more模式
hive.fetch.task.conversion=more 以下三种情况不走mr程序 全表扫描查询 字段查询 limit查询
-
-
hive本地执行模式
- 建议在开发环境中开启
正常情况下: hive sql--->mapreduce--->yarn(分布式执行)--->hdfs结构化数据--->处理结果 本地执行模式: hive sql--->mapreduce--->local mode(本地模式 单机执行)--->hdfs结构化数据--->处理结果 hive> SET mapreduce.framework.name=local; 该参数决定了hive中最终的mr程序是什么执行模式 如果是local 所有的mr程序都走本地 如果yarn 都走yarn. 0.7版本之后: SET hive.exec.mode.local.auto=false; 该参数可以自动决定是否切换本地模式。默认不开启 如果设置为true,会根据下述三个标准进行自动切换 切换标准: 总共的数据量小于128M maptask个数小于4个 reducetask个数要么为0 要么为1
-
join中的map side join
-
通常认为进行数据的join 应该把相关联的数据发送到同一个reduce 在reduce中完成关联的判断 这种称之为common join(reduce join)
-
当下hive版本中 默认开启了map端的join 如果可以转化满足map端join的条件 hive将会自动转化
何谓map 端join? 首先启动第一个mr程序把小表的文件读取 变成hashtable 做分布式缓存发送 然后启动一个只有mapper阶段的mr程序 通过maptask读取一条记录和上一步的缓存做关联 在map端就完成了join的操作
-
在实际使用中,通过下面这个参数设置小表阈值。
set hive.mapjoin.smalltable.filesize= 25000000; 设置多大以下为小表
-
-
大表join大表
-
如果有空值 空值过滤可以优化查询时间
-
空值转换
-
把空值转换成某一个非空字符串
CASE WHEN a.id IS NULL THEN 'hive' ELSE a.id END = b.id 弊端如果这样的空值过多 会造成reduce数据倾斜
-
把空值转换成若干个随机的非空字符串
CASE WHEN a.id IS NULL THEN concat('hive', rand()) ELSE a.id END
-
-
大小表之间的join
不管是大join小 还是小join大 当下的hive版本已经自动处理好了 不需要额外的特别设置。
hive老的版本中 把小表写在前面 提高join的速度
-
-
group by优化
-
如果数据都发送到reduce进行分组后的操作 容易产生数据倾斜
-
记住如果数据本身不平衡 可能会导致数据倾斜 请开启下面的选项
有数据倾斜的时候进行负载均衡(默认是 false) set hive.groupby.skewindata = true;
-
-
maptask个数调整
-
小文件场景(想法进行合并)
- 上传hdfs之前进行本地合并 Java IO—>block size
- 上传中间进行合并 appendToFile
- 上传之后使用hadoop archive小文件归档
-
大文件场景(想法进行拆分)
-
在设置hdfs存储block size的时候进行改变
-
使用distribute by把原来表的数据随机分散成若干个部分 set mapreduce.job.reduces =10;
然后在针对数据进行处理 就可以增加maptask个数
create table a_1 as select * from a distribute by rand(123);
-
-
-
reducetask个数调整
-
set mapreduce.job.reduces = -1 默认hive自己会根据任务情况进行决定
-
当然用户可以手动指定个数 不一定生效 hive会保证某些逻辑能够正常执行
order by 全局排序 意味着只能有一个reducetask hive为了满足能够正常执行 自己决定
-
-
hive的并行执行机制
-
hive中sql会最终编译成若干个不同的阶段stage执行 如果当中某些阶段没有依赖 可以尝试开始并行执行
-
默认是没有开启的 需要开启该机制 并且指定最大可以通过并行执行的个数
set hive.exec.parallel=true; //打开任务并行执行 set hive.exec.parallel.thread.number=16; //同一个 sql 允许最 大并行度,默认为 8
-
注意:并行执行意味着短时间内资源的大量消耗 通常在集群空闲时期开启
-
-
严格模式
-
默认情况下 hive执行的是非严格模式
-
可以通过下面的参数开启严格模式
set hive.mapred.mode = strict;
-
如果是严格模式,以下三种操作被禁止
- 分区表查询必须指定where分区条件 禁止全表扫描
- order by查询必须跟limit语法 限制返回的条数
- 禁止笛卡尔积查询
-
-
jvm重用机制
- 默认情况下在mr中,不管是maptask还是reducetask 本质都是jvm进程
- 默认一个jvm运行一个task 运行完毕 释放资源 销毁jvm
- 如果开启重用机制 就可以在本次job中多次重复使用该同一个jvm 避免资源频繁的申请销毁
- 对其他job来说 就会形成一直霸占资源的场景
-
mr推测执行机制
- 默认maptask reducetask都是开启的
- 找出拖后腿的task 为其启动备份task 两个同时处理同一份数据。谁先执行完,谁的结果最为最终结果。