Hive 优化
1. 架构优化
Hive支持多种执行引擎,分别是 MapReduce、Tez、Spark、Flink。可以通过hivesite.xml文件中的hive.execution.engine属性控制。
矢量化查询执行:
矢量化查询(要求执行引擎为Tez)执行通过一次批量执行1024行而不是每行一行来提 高扫描,
聚合,过滤器和连接等操作的性能,这个功能一显着缩短查询执行时间。
set hive.vectorized.execution.enabled = true; -- 默认 false set hive.vectorized.execution.reduce.enabled = true; -- 默认 false
备注:要使用矢量化查询执行,必须用ORC格式存储数据
成本优化器:
Hive的CBO是基于apache Calcite的,Hive的CBO通过查询成本(有analyze收集的统 计信息)会生成有效率的执行计划,
最终会减少执行的时间和资源的利用,使用CBO 的配置如下:
SET hive.cbo.enable=true; --从 v0.14.0默认 true SET hive.compute.query.using.stats=true; -- 默认false SET hive.stats.fetch.column.stats=true; -- 默认false SET hive.stats.fetch.partition.stats=true; -- 默认true
定期执行表(analyze)的分析,分析后的数据放在元数据库中。
分区表:
对于一张比较大的表,将其设计成分区表可以提升查询的性能,对于一个特定分区的 查询,
只会加载对应分区路径的文件数据,所以执行速度会比较快。
分区字段的选择是影响查询性能的重要因素,尽量避免层级较深的分区,这样会造成 太多的子文件夹。一些常见的分区字段可以是:
- 日期或时间。如year、month、day或者hour,当表中存在时间或者日期字段时
- 地理位置。如国家、省份、城市等
- 业务逻辑。如部门、销售区域、客户等等
分桶表:
与分区表类似,分桶表的组织方式是将HDFS上的文件分割成多个文件。
分桶可以加快数据采样,也可以提升join的性能(join的字段是分桶字段),因为分桶可 以确保某个key对应的数据在一个特定的桶内(文件),
巧妙地选择分桶字段可以大幅 度提升join的性能。
通常情况下,分桶字段可以选择经常用在过滤操作或者join操作的字段。
存储格式:
存储格式一般需要根据业务进行选择,生产环境中绝大多数表都采用TextFile、 ORC、Parquet存储格式之一。
TextFile是最简单的存储格式,它是纯文本记录,也是Hive的默认格式。其磁盘开销 大,查询效率低,更多的是作为跳板来使用。
RCFile、ORC、Parquet等格式的表都 不能由文件直接导入数据,必须由TextFile来做中转。
Parquet和ORC都是Apache旗下的开源列式存储格式。列式存储比起传统的行式存 储更适合批量OLAP查询,并且也支持更好的压缩和编码。
选择Parquet的原因主要 是它支持Impala查询引擎,并且对update、delete和事务性操作需求很低。
压缩:
压缩技术可以减少map与reduce之间的数据传输,从而可以提升查询性能,关于压 缩的配置可以在hive的命令行中或者hive-site.xml文件中进行配置。
SET hive.exec.compress.intermediate=true
关于压缩的编码器可以通过mapred-site.xml, hive-site.xml进行配置,也可以通过命 令行进行配置,如:
-- 中间结果压缩 SET hive.intermediate.compression.codec=org.apache.hadoop.io.compr ess.SnappyCodec ; -- 输出结果压缩 SET hive.exec.compress.output=true; SET mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodc
2.参数优化:
本地模式:
当Hive处理的数据量较小时,使用本地模式速度更快。
SET hive.exec.mode.local.auto=true; -- 默认 false SET hive.exec.mode.local.auto.inputbytes.max=50000000; SET hive.exec.mode.local.auto.input.files.max=5; -- 默认 4
一个作业只要满足下面的条件,会启用本地模式
- 输入文件的大小小于 hive.exec.mode.local.auto.inputbytes.max 配置的大 小
- map任务的数量小于 hive.exec.mode.local.auto.input.files.max 配置的 大小
- reduce任务的数量是1或者0
严格模式:
所谓严格模式,就是强制不允许用户执行3种有风险的HiveQL语句。
- 查询分区表时不限定分区列的语句;
- 两表join产生了笛卡尔积的语句;
- 用order by来排序,但没有指定limit的语句。
要开启严格模式,需要将参数 hive.mapred.mode 设为strict(缺省值)。
该参数可以不在参数文件中定义,在执行SQL之前设置(set hive.mapred.mode=nostrict )
JVM重用:
当执行轻量级作业,开启JVM重用会比较有效。
# 代表同一个MR job中顺序执行的5个task重复使用一个JVM,减少启动和关闭的开销 SET mapreduce.job.jvm.numtasks=5;
这个功能的缺点是,开启JVM重用将一直占用使用到的task插槽,以便进行重用,直 到任务完成后才能释放。
如果某个“不平衡的”job中有某几个reduce task执行的时间 要比其他Reduce task消耗的时间多的多的话,
那么保留的插槽就会一直空闲着却无 法被其他的job使用,直到所有的task都结束了才会释放。
并行执行:
Hive的查询通常会被转换成一系列的stage,这些stage之间并不是一直相互依赖的, 可以并行执行这些stage,通过下面的方式进行配置:
SET hive.exec.parallel=true; -- 默认false SET hive.exec.parallel.thread.number=16; -- 默认8
并行执行可以增加集群资源的利用率,如果集群的资源使用率已经很高了,那么并行 执行的效果不会很明显。
推测执行:
启动备份任务,和原来的任务同时执行,处理同一份数据,先完成的作为最终结果。
set mapreduce.map.speculative=true set mapreduce.reduce.speculative=true set hive.mapred.reduce.tasks.speculative.execution=true
小文件合并:
在map执行前合并小文件,减少map数:
# 缺省参数 set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
在Map-Reduce的任务结束时合并小文件:
# 在 map-only 任务结束时合并小文件,默认true SET hive.merge.mapfiles = true; # 在 map-reduce 任务结束时合并小文件,默认false SET hive.merge.mapredfiles = true; # 合并文件的大小,默认256M SET hive.merge.size.per.task = 268435456; # 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件 merge SET hive.merge.smallfiles.avgsize = 16777216;
Fetch模式:
Fetch模式是指Hive中对某些情况的查询可以不必使用MapReduce计算。select col1, col2 from tab ;
可以简单地读取表对应的存储目录下的文件,然后输出查询结果到控制台。
在开启 fetch模式之后,在全局查找、字段查找、limit查找等都不启动 MapReduce 。
# Default Value: minimal in Hive 0.10.0 through 0.13.1, more in Hive 0.14.0 and later hive.fetch.task.conversion=more
3.SQL优化
列裁剪和分区裁剪:
列裁剪是在查询时只读取需要的列;分区裁剪就是只读取需要的分区。
简单的说:select 中不要有多余的列,坚决避免 select * from tab; 查询分区表,不读多余的数据;
sort by 代替 order by:
order by 是全局排序,只有一个reduce
如果使用sort by,那么还是会视情况启动多个reducer进行排序,并且保证每个 reducer内局部有序。
为了控制map端数据分配到reducer的key,往往还要配合 distribute by 一同使用。
如果不加 distribute by 的话,map端数据就会随机分配到 reducer。
group by 代替 count(distinct):
当要统计某一列的去重数时,如果数据量很大,count(distinct) 会非常慢。
原因与 order by类似,count(distinct)逻辑只会有很少的reducer来处理。
-- 原始SQL select count(distinct uid) from tab; -- 优化后的SQL select count(1) from (select uid from tab group by uid) tmp;
即:在group by 外层统计数量
group by 配置调整:
原文地址:https://www.cnblogs.com/wanghzh/p/15015861.html
- 关于正则表达式第三篇(r3笔记第52天)
- 关于正则表达式第四篇(r3笔记第53天)
- 外部表简单总结(r3笔记第51天)
- 通过shell脚本监控sql执行频率(r3笔记第50天)
- 和Null有关的函数(r3笔记第48天)
- 关于查询转换的一些简单分析(二) (r3笔记第68天)
- 跨网络拷贝文件的简单实践(r3笔记第67天)
- 关于enq: TX - allocate ITL entry的问题分析(r3笔记第66天)
- Tensorflow学习:使用Tensorflow搭建深层网络分类器
- 关于interval partitioning(r3笔记65天)
- Spark Tips4: Kafka的Consumer Group及其在Spark Streaming中的“异动”(更新)
- 关于数据库中的一些name(r3笔记第64天)
- 码农的瑞士军刀-脚本语言
- shell基础学习总结(一) (r3笔记第63天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 猿实战06——不一样的地址管理
- Redis常用命令详解
- three.js 制作逻辑转体游戏(下)
- ROS机器人TF基础(坐标相关概念和实践)
- (在模仿中精进数据可视化01) 全国38城居住自由指数可视化
- js字符串/数组常用方法总结
- ThinkPHP5+mpdf 实现富文本生成 PDF文件
- nodejs使用readline逐行读取和写入文件
- go语言逐行读取和写入文件
- SpringBoot中Tomcat是如何启动的
- 自定义注解详解及应用
- 微服务开源框架TARS 之 框架服务解析
- dotnet 在 UOS 国产系统上使用 Xamarin Forms 创建 xaml 界面的 GTK 应用
- K8s集群上使用Helm部署2.4.6版本Rancher集群
- VMware下安装CentOS