乱用Hive调优,你的任务越调优越慢
有个小伙伴给我发了段代码,其中一个job是一个子查询很简单,数据也不是很大,大概也就3亿,100多个字段,跑3小时一直没跑出来,任务没有报错,进度一直正常;尝试了各种方法,参数优化,udf重构等。
部分脱敏后代码如下:
运行截图如下:

后来我让他发我看下完整代码以及参数配置;发现其中有个参数开启了向量化(矢量化),一般来说开启了矢量化,本来是为了一片好心提高计算效率的。但但是很多函数是不支持的矢量化的,造成数据量很大的时候就会帮倒忙。
询问为啥加这个参数,说是公众号看的调优参数哈,噗。一个任务脚本配置了20多个参数.....总之,牛逼。
让我们看下官网,为啥会有这个问题?
矢量化查询执行是 Hive 的一项功能,可大大降低典型查询操作(如扫描、过滤器、聚合和连接)的 CPU 使用率。标准查询执行系统一次处理一行。这涉及执行内部循环中的长代码路径和重要的元数据解释。矢量化查询执行通过一次处理 1024 行的块来简化操作。在块内,每一列都存储为一个向量(原始数据类型的数组)。算术和比较等简单操作是通过在紧密循环中快速迭代向量来完成的,循环内没有或很少有函数调用或条件分支。这些循环以简化的方式编译,使用相对较少的指令,平均而言,在更少的时钟周期内完成每条指令,通过有效地使用处理器流水线和高速缓存存储器。
1.为啥向量化可以提高效率?
简单来说就是传统hive的计算是一次处理一行数据,矢量化开启一次处理1024行数据,看上去确实可以提高速度。传统方式这些运算符设计为一次处理一行。一次处理一行的操作员效率不高,因为需要许多虚函数调用来处理扫描的每一行。此外,当Operator一次处理一行时,无法利用支持 SIMD 指令集(如 SSE 或 AVX)的现代 CPU 架构。
Hive的矢量化是一次处理一批次行,而不是一次处理一行。与基于行的执行相比,向量化执行避免了大量的虚函数调用,从而提高了指令和数据缓存的命中率,它们一起处理一批行,而不是一次处理一行。与基于行的执行相比,向量化执行避免了大量的虚函数调用,从而提高了指令和数据缓存的命中率
但是矢量化的使用是有限制的,不是对所有的语法都是支持,使用不当会适得其反,这也就是为啥矢量化默认是关闭的,需要手动开启。就是为了防止大家不懂的乱用。
看官网矢量化支持的表达式与类型
很明显我们前面小伙伴使用的split函数并不在此列,所以使用split开启矢量化时反而批处理适得其反。取消矢量化参数后,程序10多分钟就跑完了。
而且矢量化的使用apache版本的hive的表存储要是orc格式文件存储。cdh集群6.x支持parquet格式的使用,这块cdh做了二开,性能相比传统提升了大概30%左右。
2. 关于组件调优几点看法
大数据开发面临的代码调优一般就分为两类,代码调优+参数调优。
代码调优我这里先不说。说一下大家常关注的参数调优。参数调优又分为集群层面参数调优和用户层面参数调优。我们大部分大数据开发(数仓开发)小伙伴在企业里需要参数调优的都是用户角度参数调优;
因为集群层面的参数调优一般是大数据运维,在建设集群与维护集群时就已经配置好了比如下:
这些大家在公众号网上看到的参数都是集群层面优化好的,一般来说大数据运维会结合公司的业务进行调优适配的,很多参数是不需要大家去调优的,而且很多参数是默认自动优化的等等。
大家在企业日常运行代码时,如果你们集群运维做的好,甚至不需要加什么参数(我个人运维集群架构这块最讨厌小白算法分析师不懂瞎搞搜一堆乱七八糟的参数调优进去,然后代码越跑越慢),更多的是从代码层面进行优化,而不是写一堆堆参数放上去。代码层面的优化,逻辑的设计,优质的代码才是根本上避免问题的出现。
参数调优更多的是应对一些生产上特殊场景特殊情况的使用,而不是常规化使用;
大家学习东西要沉下心去研读官网,权威书籍,这个进步是明显的。而不是读一些人云亦云的转来转去的文章。客观来说,国内大数据类的公众号质量是真的很差,基本都是一些千禧年00后运营的,有些甚至还没毕业工作。主要是真的大佬都在忙着闷声发大财,低调向上,务实不务虚。
吐槽一句,多用google,质量跟百度检索出来的真有很大差别。
