Hive调优

本文介绍了Hive的调优方案,包括数据压缩、选择合适的存储方式(如Orc+Snappy)、Fetch抓取策略、join优化技巧、本地模式应用以及SQL优化方法,如列裁剪和分区裁剪。同时提到JVM重用和explain执行计划的重要性,以及如何管理和限制推测执行。
摘要由CSDN通过智能技术生成

Hive调优方案介绍
    1. 数据压缩.

        判断一种压缩协议好与坏的标准: 压缩后文件占比, 解压速度, 压缩速度.
        Hive的底层是MR程序, 所以Hive的压缩本质上还是MR的压缩, 它(MR程序)支持GZip, Bzip2, Lzo, Snappy(推荐使用: 因为更均衡)等协议.
        数据压缩分为两项, 即: Map端压缩 和 Reduce端压缩.
            Map端压缩的目的:
                降低Reduce端拉取的数据量, 减少传输, 提高效率.
            Reduce端压缩的目的:
                降低写入磁盘的数据量, 减小结果文件的大小, 提高磁盘利用率.


    2. 存储方式.
        Hive表的存储格式分为 行存储 和 列存储两种, 其中:
            行存储主要有两种方式: TextFile(默认的), SequenceFile
            列存储主要有两种方式: Orc(推荐, 更均衡), Parquet(Spark中用的较多)
        行存储 和 列存储的区别是什么?
        答:

行存储:
                优点:  select * from ... 方式, 查询数据, 效率较高.
                缺点:
                    1. 数据密集度低, 磁盘利用率低.
                    2. select 列1, 列2..方式, 效率低.
            列存储:
                优点:
                    1. 数据密集度较高, 磁盘利用率高.
                    2. select 列1, 列2 方式效率高.
                缺点:
                    select * 方式效率相对较低, 但是实际开发中, 这种写法几乎不用.
        细节:
            1. 实际开发中, 如果 存储格式 和 压缩协议 你也不知道用谁了, 推荐使用: Orc + Snappy.
            2. 列存储的底层是用 二进制 的形式来存储数据的.


    3. Fetch抓取
       

我们知道Hive的底层要转MR任务来执行, 而MR程序的计算速度是非常慢的, 如果执行的是简单的HiveSQL, 没必要转MR程序, 直接执行即可.
        大白话, Fetch抓取的意思是: HiveSQL 底层能不转MR, 就不转MR, 而是直接执行.
        那, 哪些SQL不会转MR程序的呢?
            1. select * 全表扫描.
            2. select 列1, 列2 字段扫描.
            3. limit 分页查询.
            4. 一些简单的SQL语句.
        通过 set hive.fetch.task.conversion=值;        的方式, 可以设置本地抓取模式.
            more(默认值):  上述四项都不走MR.
            minimal: 全表扫描, 列扫描, 分页查询不走MR.
            none: 所有HiveSQL都走MR.


    4. 本地模式
       

大白话: 如果HiveSQL非要转MR程序, 能在本地执行, 就尽量不要交给Yarn来调度, 因为可能会涉及到跨域(跨机器)传输, 降低效率.


    5. join优化
       

 join优化有3种情况, 即:
            小表join大表:
                1. 开启Map端join, 在Map端(内存中)对数据做合并, 降低Reduce端拉取的数据量, 一方面提高传输效率, 另一方面可以防止出现数据倾斜.
                2. 其实join优化你开与不开, 本质没有太大的区别, 因为Hive为了提高查询效率, 已经设置了, 自动join优化.
            大表join大表:
                假设有A表(100W条数据, id列50W是空),   B表(60W条数据, id列40W空), 如果此时两张表根据 id列做关联查询, 会有大量的空值.
                原始写法:
                    select * from A inner join B on A.id = B.id;        -- 弊端是: id列有大量的空值, 无意义的操作较多.
                1. 空值过滤.
                    select * from A inner join (select * from B where id is not null) B on A.id = B.id;   -- 弊端: 会过滤掉大量的数据, 可能也会把有效的数据过滤掉
                2. 空值转换.
                    # 2.1 不随机分布, 固定值.
                    select * from A inner join (
                        select 列1, 列2.., case when id is null then 10 end as id from B
                    ) B on A.id = B.id;   -- 虽然能解决, 但是null值过多, 会导致10过多, 将来出现数据倾斜的概率较大.

                    # 2.2 随机分布, 可变值..
                    select * from A inner join (
                        select 列1, 列2.., case when id is null then concat(值, rand()) end as id from B
                    ) B on A.id = B.id;
            分桶表 join 分桶表:
                前提:
                    1. 两张表都是分桶表.
                    2. 某表的分桶数量 是另外表 分桶数量的 偶数倍.
                结论:
                    表join连接查询的时候, 可以用 分桶字段替代 关联字段, 即:
                    原始SQL:
                        select * from A join B on A.id = B.id;
                    优化后SQL:
                        select * from A join B on A.分桶字段 = B.分桶字段;


    6. SQL常规优化
   

    1. 列裁剪.     能写 select 列1, 列2 就不要写 select *
    2. 分区裁剪.   查询时, 如果是分区表, 记得写 where 分组字段
    3. count(id). 如果数据量大, 容易出错, 可以改成 先分组, 后统计, 虽然会转2个MR, 执行速度慢了, 但是数据量大的情况下, 也可以成功执行.
    4. 避免笛卡尔积的情况.
    5. group by数据倾斜
            描述: 分配给ReduceTask端的数据不均衡导致的问题.  例如: 1个ReduceTask处理100W条数据, 另1个ReduceTask处理100条数据.
            解决方案:
                手动开启负载均衡, 程序的底层会转两个MR程序来执行该任务, 第1个MR程序负责把倾斜的数据随机打散, 交给不同的ReduceTask来处理.
                第1个MR程序的(Reduce端结果) 作为 第2个MR程序的Map段数据源, 然后由第2个MR的Reduce负责合并数据.
            大白话:
                手动开启负载均衡, 由第1个MR随机打散(倾斜的)数据, 由第2个MR来合并.
    6. 动态分区
            手动调大动态分区数, 默认动态分区上限是1000, 如果HQL分区数量超过它, 会报错, 我们调大分区数即可.
            小细节: 动态分区的时候, 可以关闭严格模式, 因为严格模式要求: 动态分区时至少有1个静态分区.


   
    7. 调整MR的任务数.
       

调整MapTask任务数:
            1. 1个切片 = 1个MapTask任务 = 1个分好区, 排好序, 规好约的文件.
            2. 减小切片大小(默认: 128MB) = 增多MapTask任务数,   增大切片大小 = 减少MapTask任务数.
        调整ReduceTask任务数:
            1. 1个分区 = 1个ReduceTask任务 = 1个结果文件
            2. 手动设置分区数, 即可修改ReduceTask的任务数量.


    8. 并行执行.

        默认情况下, HiveSQL只会执行1个阶段, 如果多阶段之间依赖度不高, 我们可以开启并行执行机制.
        并行执行机制, 默认并行度是 8, 我们可以调大一些.


    9. 严格模式.

        这个严格模式指的是 禁用低效的SQL, 即: 如果SQL比较低效, 压根儿不让你执行.  这个严格模式 和 动态分区的严格模式可以不是同1个.
        问: 哪些SQL属于低效的SQL呢?
        答:
            1. select *.. 全表扫描
            2. order by的时候没有加 limit
            3. 笛卡尔积.


    10. jvm重用.
 

       Hive2.X已开启, 无需设置, Hive2.X以前Container容器用一次就释放了, 开启JVM重用, 可以重复利用这些Container资源容器.
    11. explain执行计划
        在HQL前加 explain执行计划, 查看SQL的执行分几个阶段, 阶段越少, 执行速度越快.
    12. 推测执行
        实际开发, 禁用它, 类似于木桶效应.
        假设HQL转了3个MapReduce任务, 其中前两个任务执行速度都较快, 但是第三个任务执行速度太慢了, 会拖慢整个MR程序的执行进度.
        此时程序会开启1个新的任务, 负责和那个慢的任务做同样的事儿, 采用谁先执行完, 用谁的结果. 无意义, 因为已经很慢了, 开启新任务后会更慢.

关于Hive的调优, 大家了解即可, 为了简化大家的记忆, 我给大家总结四句话(仅代表个人观点):
    1. 更改硬件.
    2. 增大或者开启某些设置.      -- Fetch抓取, 开启负载均衡(解决group by数据倾斜), 动态分区数, join优化, 开启严格模式(禁用低效SQL)
    3. 减小或者关闭某些设置.      -- 推测执行, 严格模式(动态分区的), MapReduce的任务数.
    4. 减少IO.                 -- 数据压缩, 存储格式.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值