精华内容
下载资源
问答
  • set hive.auto.convert.join = true 默认为true,意思就是,系统会以mapjoin为优先,这样运行速度更快。 load LOAD DATA LOCAL INPATH '/home/dayongd/Downloads/employee.txt' OVERWRITE INTO TAB

    CTE(common table expression)

    with a as (select * from table1)
    select * from a;
    

    MapJoin

    小表关联大表,解决数据倾斜的问题

    set hive.auto.convert.join = true              //默认为true
    set hive.mapjoin.smalltable.filesize=25000000 //设置小表不超过多大时开启 mapjoin 优化  ,默认25MB左右
    

    系统会以mapjoin为优先,这样运行速度更快。

    这边就必须要提一下数据倾斜

    由于数据大量的集中到一点,造成数据热点,
    hadoop框架特点:
    不怕数据多,就怕数据倾斜;
    job数较多作业运行的速度就慢(因为每个job启动之后在rousourcemanager那都要走一系列的流程),如having的运行就会产生很多的job,所以尽量在where进行数据清洗;
    聚合函数通常不会有数据倾斜的问题;
    如何发现数据倾斜:
    在8088端口,查看任务进度维持在99%或者100%附近,查看任务监控界面,发现只有少量的reduce任务未完成,因为其处理的数据量和其他reduce的差异过大,最长时间远大于平均时间
    容易导致数据倾斜的情况:
    groupby 不和聚合函数搭配使用
    count(distinct)
    小表关联超大表
    特殊值过多,如null或者0,会让reduce非常耗时
    针对问题的解决办法

    问题1:空值产生的数据倾斜:
    把为空的数据挑出来,不参与排序,最后union all 进去

    select * from table1 a join table2 b on a.id is not null and a.id =b.id
    union all 
    select * from table1 c where c.id is null;
    
    

    给空值赋一个新的值,这样效率更高,(只查一次表,减少IO和作业数)

    select * from table1 a left jojin table2 b 
    on case when a.id is null then concat('hive',rand()) else a.id end = b.id;
    

    2.不同的数据类型关联导致产生数据倾斜
    例如有些id的类型为int,有些id的类型为string,reduce的时候,会导致string类型的被分到一个reducer中
    解决办法:转型

    select * form table a left join table2 b on 
    a.id = cast(b.id as string )
    

    3,大小表关联查询,导致数据倾斜
    进行mapjoin操作,将小表加载进内存中,直接在mapper端就做好join。

    load

    LOAD DATA LOCAL INPATH '/home/dayongd/Downloads/employee.txt' 
    OVERWRITE INTO TABLE employee;
    -- LOCAL表示文件位于本地,OVERWRITE表示覆盖现有数据
    LOAD DATA LOCAL INPATH '/home/dayongd/Downloads/employee.txt' 
    OVERWRITE INTO TABLE employee_partitioned  PARTITION (year=2014, month=12);
    -- 没有LOCAL,文件位于HDFS文件系统中
    

    insert

    可以把文件导出到本地。

    INSERT OVERWRITE/INTO TABLE tablename1 
    [PARTITION (partcol1=val1, partcol2=val2 ...)] 
    select fileds,... from tb_other;
    

    数据交换

    但只能导出到hdfs.

    IMPORT和EXPORT用于数据导入和导出
    常用于数据迁移场景
    除数据库,可导入导出所有数据和元数据
    EXPORT TABLE employee_partitioned partition (year=2014, month=11) TO '/tmp/output5';
    IMPORT TABLE employee_partitioned partition (year=2014, month=11) FROM '/tmp/output5';
    
    

    数据排序

    order by

    全局排序 ,只使用一个reduce执行(就算你设置多个reduce.tasks也没用,还是只有一个reduce工作)

    sort by

    //设置reduce个数为3
    set mapred.reduce.tasks=3;
    

    sort by 不是全部排序,其在数据进入reducer前完成排序
    只能保证在同一个reducer的输出有序,
    最后的结果是多个reducer的合并,

    distribute by

    分区,没有排序功能
    控制在map端 如何拆分数据给reduce端,
    Hive会根据distribute by 后面列,对应reduce的个数进行分发。
    常于sort by 组合使用

    cluster by

    不怎么用,效果相当于distribute by + sort by ,但效率不高

    窗口函数

    语法

    Function (arg1,..., arg n) OVER ([PARTITION BY <...>] [ORDER BY <....>] [<window_clause>])
    

    可以同时使用多个窗口函数,over就是开窗, partition就是类似于分区,每个分区分开计算,最后结果再放到一起。

    排序功能

    row_number()
    对所有数值输出不同的序号,序号唯一连续

    SELECT 
    name, dept_num, salary, 
    ROW_NUMBER() OVER (partition by dept_num order by salary desc) AS row_num
    FROM employee_contract; 
    

    结果,根据分区分别排序,然后计数

    name    dept_num        salary  row_num
    Steven  1000    6400    1
    Lucy    1000    5500    2
    Michael 1000    5000    3
    Wendy   1000    4000    4
    Will    1000    4000    5
    Mike    1001    6400    1
    Jess    1001    6000    2
    Lily    1001    5000    3
    Richard 1002    8000    1
    Wei     1002    7000    2
    Yun     1002    5500    3
    Time taken: 40.44 seconds, Fetched: 12 row(s)
    
    

    rank()
    对相同数值,输出相同的序号,下一个序号跳过(1,1,3)

    DENSE_RANK()
    对相同数值,输出相同的序号,下一个序号连续(1,1,2)

    聚合

    以sum为例。这边比较难理解的就是他分区和计算的含义,这里的orderby相当于又规定了一个范围,从开始到当前,orderby一样的算在一个范围中

    SELECT 
    name, dept_num, salary, 
    sum(salary) OVER (partition by dept_num ) AS row_sum
    FROM employee_contract; 
    

    结果

    name    dept_num        salary  row_sum
    Lucy    1000    5500    29900
    Steven  1000    6400    29900
    Wendy   1000    4000    29900
    Will    1000    4000    29900
    Michael 1000    5000    29900
    zhangdan1000    5000    29900
    Mike    1001    6400    17400
    Jess    1001    6000    17400
    Lily    1001    5000    17400
    Richard 1002    8000    20500
    Yun     1002    5500    20500
    Wei     1002    7000    20500
    Time taken: 36.996 seconds, Fetched: 12 row(s)
    
    

    在原来基础上加上orderby

    SELECT 
    name, dept_num, salary, 
    sum(salary) OVER (partition by dept_num order by salary desc) AS row_sum
    FROM employee_contract; 
    

    结果

    name    dept_num        salary  row_num
    Steven  1000    6400    6400
    Lucy    1000    5500    11900
    Michael 1000    5000    21900
    zhangdan1000    5000    21900
    Wendy   1000    4000    29900
    Will    1000    4000    29900
    Mike    1001    6400    6400
    Jess    1001    6000    12400
    Lily    1001    5000    17400
    Richard 1002    8000    8000
    Wei     1002    7000    15000
    Yun     1002    5500    20500
    
    

    分析

    CUME_DIST
    小于等于当前值的行数/分组内总行数
    LEAD/LAG(col,n)
    某一列进行往前/后第n行值(n可选,默认为1)
    FIRST_VALUE
    对该列到目前为止的首个值
    LAST_VALUE
    到目前行为止的最后一个值

    SELECT 
    name, dept_num, salary,
    LAG(salary, 2, 0) OVER(PARTITION BY dept_num ORDER BY salary) AS lag
    FROM employee_contract
    

    函数里面三个参数,第一个是移动的字段,第二个是向后的个数,,第三个是,没有对应参数时的默认值。
    结果如下

    name    dept_num        salary  lag
    Wendy   1000    4000    0
    Will    1000    4000    0
    Michael 1000    5000    4000
    zhangdan1000    5000    4000
    Lucy    1000    5500    5000
    Steven  1000    6400    5000
    Lily    1001    5000    0
    Jess    1001    6000    0
    Mike    1001    6400    5000
    Yun     1002    5500    0
    Wei     1002    7000    0
    Richard 1002    8000    5500
    Time taken: 30.078 seconds, Fetched: 12 row(s)
    
    SELECT 
    name, dept_num, salary,
    LEAD(salary, 2,0) OVER(PARTITION BY dept_num ORDER BY salary) AS lead
    FROM employee_contract
    

    结果如下

    name    dept_num        salary  lead
    Wendy   1000    4000    5000
    Will    1000    4000    5000
    Michael 1000    5000    5500
    zhangdan1000    5000    6400
    Lucy    1000    5500    0
    Steven  1000    6400    0
    Lily    1001    5000    6400
    Jess    1001    6000    0
    Mike    1001    6400    0
    Yun     1002    5500    8000
    Wei     1002    7000    0
    Richard 1002    8000    0
    Time taken: 38.301 seconds, Fetched: 12 row(s)
    

    窗口定义

    窗口定义由[<window_clause>]子句描述
    在这里插入图片描述

    SELECT
    name, dept_num AS dept, salary AS sal,
    MAX(salary) OVER (PARTITION BY dept_num ORDER BY name ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) win1
    FROM employee_contract 
    

    根据dept_num分区,根据name排序,在前2行到当前行,寻找最大值
    运行结果

    name    dept    sal     win1
    Lucy    1000    5500    5500
    Michael 1000    5000    5500
    Steven  1000    6400    6400
    Wendy   1000    4000    6400
    Will    1000    4000    6400
    zhangdan1000    5000    5000
    Jess    1001    6000    6000
    Lily    1001    5000    6000
    Mike    1001    6400    6400
    Richard 1002    8000    8000
    Wei     1002    7000    8000
    Yun     1002    5500    8000
    Time taken: 39.927 seconds, Fetched: 12 row(s)
    
    
    展开全文
  • Hive-排序与窗口函数

    2020-09-04 18:20:48
    sort by:每个reducer内部排序, 随机/均匀地分给多个reducers,防止数据倾斜 set mapreduce.job.reduces= ; distribute by: 分区排序,分配多个reducer进行处理(结合sort by使用,写在sort by之前,意为先分区...

    排序

    order by:全局排序,一个reducer

    • 默认升序ASC
    • 可以按别名/多个列排序

    sort by:每个reducer内部排序, 随机/均匀地分给多个reducers,防止数据倾斜

    set mapreduce.job.reduces= ;

    distribute by: 分区排序,分配多个reducer进行处理(结合sort by使用,写在sort by之前,意为先分区再排序)

          distribute by 和 sort by 字段相同时可以使用cluster by,但此时排序只能是升序

    distribute by ... sort by ...
    

     

    窗口函数

    over() 对每条数据都开了一个独立的窗口,括号内为窗口数据集大小

    按日期累加:

    select date, cost, sum(cost) over(order by date)
    from

    排序函数:

    rank() / dense_rank() / row_number()

    row_number() over(partition by p_date, device_id, session_id order by client_timestamp asc) 

      partition by ... order by ... 等价于 distribute by ... sort by ...

    notes

    partition by: 建表语句有ed,查询语句无ed

    row_number(): 1234 / rank(): 1224 / desc_rank: 1223

     

    展开全文
  • Hive 知识点总结

    2020-05-09 10:41:50
    雪花模型 应用场景hive 解析 json格式的数据列转行 侧视图hive和数据库的区别hive数据的存储数据仓库的四层结构数据质量的校验: 错误值、重复值、数据不一致、缺失值hive自定义函数数据倾斜的优化原因:参数调节sql...

    hive是什么?

    Hive是基于 Hadoop 的一个数据仓库工具:
    1.hive本身不提供数据存储功能,使用HDFS做数据存储;
    hive的元数据存储:通常是存储在关系数据库如 mysql(推荐) , derby(内嵌数据库)中
    2.hive也不分布式计算框架,hive的核心工作就是把sql语句翻译成MR程序;
    3.hive也不提供资源调度系统,也是默认由Hadoop当中YARN集群来调度;
    4.可以将结构化的数据映射为一张数据库表,并提供 HQL(Hive SQL)查询功能。

    hive的架构原理

    hive由Driver组件,MetaStore组件,用户接口,hadoop四部分组成。
    Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后,将执行返回的结果输出到用户交互接口。
    1、用户接口:Client CLI(hive shell 命令行),JDBC/ODBC(java访问hive),WEBUI(浏览器访问hive)
    2、元数据:Metastore:元数据包括:表名,表所属数据库(默认是default),表的拥有者,列/分区字段,表的类型(是否是外部表),表的数据所在目录等
    默认存储在自带的derby数据库中,推荐使用MySQL存储Metastore
    3、hive 使用HDFS进行存储,使用MapReduce进行计算
    4、驱动器:Driver
    (1)解析器(SQL Parser):将SQL字符转换成抽象语法树AST,这一步一般使用都是第三方工具库完成,比如antlr,对AST进行语法分析,比如表是否存在,字段是否存在,SQL语句是否有误
    (2)编译器(Physical Plan):将AST编译生成逻辑执行计划
    (3)优化器(Query Optimizer):对逻辑执行计划进行优化
    (4)执行器(Execution):把逻辑执行计划转换成可以运行的物理计划,对于Hive来说,就是MR/Spark

    星型模型 雪花模型 应用场景

    星型模型的设计方式主要带来的好处是能够提升查询效率,因为生成的事实表已经经过预处理,主要的数据都在事实表里面,所以只要扫描事实表就能够进行大量的查询,而不必进行大量的join,其次维表数据一般比较少,在join可直接放入内存进行join以提升效率,除此之外,星型模型的事实表可读性比较好,不用关联多个表就能获取大部分核心信息,设计维护相对比较简答。
    雪花模型的设计方式是比较符合数据库范式的理念,设计方式比较正规,数据冗余少,但在查询的时候可能需要join多张表从而导致查询效率下降,此外规范化操作在后期维护比较复杂。

    hive 解析 json格式的数据

    自带解析函数:json_tuple
    create table name as select json_tuple(json字段的字段名,‘json内容的key值1’,‘json内容的key值2’…) from tableName

    列转行 侧视图

    select xx,xxx from xxx lateral view explode(xxx) 侧视图name as ;

    hive和数据库的区别

    Hive 和数据库除了拥有类似的查询语言,再无类似之处。
    1)数据存储位置
    Hive 存储在 HDFS 。数据库将数据保存在块设备或者本地文件系统中。
    2)数据更新
    Hive中不建议对数据的改写。而数据库中的数据通常是需要经常进行修改的,
    3)执行延迟
    Hive 执行延迟较高。数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。
    4)数据规模
    Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。

    hive数据的存储

    1.Hive中所有的数据都存储在HDFS中,没有专门的数据存储格式(可支持Text,SequenceFile,ParquetFile,RCFILE、ORC等)
    text:行存储,默认不压缩,序列化、反序列化开销大
    sequence:行存储,二进制,压缩率底
    RCfile:行分块,列式存储,解压效率差,读取稍慢
    Parquet:列式存储,压缩比率高,但比ORC差,存取速度快
    ORC:行分块,列式存储,压缩快,存取快,压缩率最高,RCfile升级版
    2.只需要在创建表的时候告诉 Hive 数据中的列分隔符和行分隔符,Hive 就可以解析数据。
    3.Hive 中包含以下数据模型:DB、Table,External Table,Partition,Bucket。
    db:在hdfs中表现为${hive.metastore.warehouse.dir}目录下一个文件夹
    table:在hdfs中表现所属db目录下一个文件夹
    external table:与table类似,不过其数据存放位置可以在任意指定路径
    partition:在hdfs中表现为table目录下的子目录
    bucket:在hdfs中表现为同一个表目录下根据hash散列之后的多个文件

    数据仓库的四层结构

    ODS:临时存储层 近源层 一般都是建的外部表。 --> 防止用户修改了原始数据
    PDW:数据仓库层 明细层 就是加工近源层的数据。 --> 实现宽表
    MID: 数据集市层 服务层 一般使用内部表。 -->大部分都是宽表 提取特征值 不在乎冗余 在乎业务
    APP:应用层

    数据质量的校验: 错误值、重复值、数据不一致、缺失值

    准确性:数据是否与其对应的客观实体的特征相一致;
    有效性:数据是否满足用户定义的条件或一定的域值范围内;取值范围、字段长度、正则匹配规则。(手机号码:/^1[0-9]{10}$/)
    唯一性:数据是否存在重复记录
    完整性:数据是否存在缺失记录或者缺失字段

    hive自定义函数

    udf 一进一出(敏感字段进行脱敏处理 mid5加密) udaf 多进一出 udtf 一进多出(公共字符串解析)

    public class LinkStr extends UDAF {
    private static String result="";
    public static class MyLink implements UDAFEvaluator{
    
        @Override
        public void init() {
        }
        //map的一部分功能  写业务逻辑
        public boolean iterate(String name){
            result = result.concat(name);
            return true;
        }
        //大部分是combiner功能 分组 分割
        public String terminatePartial(){
            return result;
        }
        //partition 负责处理
        public boolean merge(String name){
            return iterate(name);
        }
        //reduce的一部分功能
        public String terminate(){
            return result;
        }
    }
    }
    
    public class InitialUpper extends UDF {
        public String evaluate(final String txt){
            return txt.substring(0,1).toUpperCase()+txt.substring(1); //首字母大写
        }
    }
    

    自定义UDTF(extends Genertic UDTF->实现三个方法init(指定返回值的名称和类型)、process(处理字段一进多出)、close方法) -> 更加灵活以及方便定义bug

    数据倾斜的优化

    原因:

    1、key分部不均 2、数据本身就存在数据倾斜 3、某些sql语句本身就有数据倾斜 4、建表时考虑不周

    参数调节

    hive.map.aggr=true
    在map端部分聚合,相当于 mr中的 combiner

    hive.groupby.skewindata=true
    有数据倾斜的时候进行负载均衡,生成的查询计划会有两个MR Job
    第一个MR Job中 Map的输出结果会随机分布到reduce中,每个Reduce做部分聚合操作,并输出结果。这样处理的结果是相同的Group By Key 有可能被分发到不同的Reduce中,从而达到负载均衡的目的。
    第二个MR Job再根据预处理的数据结果按照Group By Key 分布到Reduce中(这个过程可以保证相同的Group By Key 被分布到同一个Reduce中),最后完成最终的聚合操作。

    小文件过多:
    需要合并小文件 ,可以通过set hive.merge.mapfiles=true来解决。

    sql语句的调优

    大小表join :
    将小表(关联键记录少的表)依次放到前面,这样可以触发reduce端更少的操作次数,减少运行时间。 同时可以使用Map Join让小的维度表缓存到内存。

    大表与大表进行join,如日志中部分的 userid丢失,如果取其中的 user_id 和 用户表中的user_id 关联,会碰到数据倾斜的问题。
    解决方法:把空值的key变成一个字符串加随机数(rand()),将倾斜的数据分到不同reduce上,从而达到负载均衡的目的。又由于null值在join的时候关联不上,所以处理后并不会影响最终的结果。
    case when userid is null then concat(‘hive’,rand()) else userid end
    延申出—》遗漏数据的处理,我们一般计算这个属性值的平均值,并用此值补该属性遗漏的值。

    经常遇到 count(distinct)操作,这样会导致最终只有一个 Reduce 任务。采用group by去重,再count()的方式来代替count(distinct)完成计算。
    比如计算按用户名去重后的总用户量:select count(1) from (select name from user group by name) tmp;

    使用union all+group by 替代 union

    不同数据类型关联产生数据倾斜:
    像userid 有int 有的表是string 两表进行join的时候 默认的hash操作会按照int类型的id进行分配,导致所有的string类型的id被分配到同一个reduce中
    解决; cast(useid as strin)

    (–count distinct 大量相同的特殊值:
    将值为空的情况单独处理 ,如果只是计算count distinct ,可以不用处理,直接过滤,在最后的结果加1。
    如果还要进行其他的计算,如需要groupby ,那就先将值为空的单独处理,再和其他计算结果进行union all
    group by维度过小,某值的数量过多
    采用group by去重 再count() 的方式来代替count(distinct) 完成计算)

    hive性能优化

    一、存储优化,选用ORC

    text:行存储,默认不压缩,序列化、反序列化开销大
    sequence:行存储,二进制,压缩率底
    RCfile:行分块,列式存储,解压效率差,读取稍慢
    Parquet:列式存储,压缩比率高,但比ORC差,存取速度快
    ORC:行分块,列式存储,压缩快,存取快,压缩率最高,RCfile升级版

    二、表设计优化

    1、创建分区表 (分区提供一个隔离数据和优化查询的便利方式)
    动态分区(hive.exec.dynamic.partition=true hive.exec.max.dynamic.partition.mode=nonstrict)
    静态分区要指定分区的列
    2、创建桶表 (分区针对的是数据的存储路径;分桶针对的是数据文件)
    3、拆分不同的表存储

    三、sql参数优化

    1、作业有多个可并行的job时,设置任务并行及并行个数:
    // 开启任务并行执行
    set hive.exec.parallel=true;
    // 同一个sql允许并行任务的最大线程数
    set hive.exec.parallel.thread.number=8;
    2、修改reduce、map个数,
    (一般情况下不会修改此参数,可能会造成很多小文件,或者如果reduce资源不够会一直等待,除非比较特殊的任务,前提是排除sql逻辑及数据问题)
    设置每个reduce处理的数据量
    set hive.exec.reducers.bytes.per.reducer=104857600;
    设置reduce个数
    set mapred.reduce.tasks=1;
    调整最大限制个数
    set hive.exec.reducers.max;
    3、使用mapjoin
    set hive.auto.convert.join = true;
    set hive.mapjoin.smalltable.filesize=50000000; – 默认是25M
    set hive.auto.convert.join.noconditionaltask = true; – 默认值
    set hive.auto.convert.join.noconditionaltask.size = 10000000; --默认值
    4、使用TEZ查询引擎
    set hive.execution.engine=tez;
    5、合并输入输出小文件
    –输出合并小文件
    set hive.merge.mapredfiles=true;
    set hive.merge.smallfiles.avgsize=512000000;
    set hive.merge.size.per.task=1024000000; --默认值 256M
    – 输入合并小文件,也用于调节map数量
    set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; --默认值
    set mapred.max.split.size=512000000;
    set mapred.min.split.size.per.node=256000000;
    set mapred.min.split.size.per.rack=256000000;
    set mapred.min.split.size=256000000;
    6、数据倾斜
    set hive.map.aggr=true;–在map中会做部分聚集操作,效率更高但需要更多的内存。
    set hive.groupby.skewindata=true;
    如果以上不管用,可以对倾斜的数据进行单独的sql处理。

    四、sql优化

    1、使用union all+group by 替代 union
    2、大小表使用mapjoin
    3、用in 替代join查询
    4、从逻辑上看有无优化的点
    5、避免笛卡尔积

    五、开启本地模式

    hive.exec.mode.local.auto=true
    hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间可以明显缩短。

    几个排序的区别

    order by 全局排序
    sort by 每个reducer内部排序
    distinct by 类似MR中的partition 进行分区,结合sort by 使用。放在 distinct by后面。
    cluster by 当distinct by 和sort by 字段相同时,可以使用cluster by 但是只能升序排序。

    窗口函数

    rank() 排序相同时会重复,总数不会变
    dense_rank() 排序相同时会重复,总数会变
    row_number() 会根据顺序排序
    over()子句:
    聚合函数COUNT、SUM、MIN、MAX、AVG
    over(partition by xx order by xxx)
    LAG 和 LEAD 函数 可以返回上下数据行的数据。
    window子句;

    • PRECEDING:往前
    • FOLLOWING:往后
    • CURRENT ROW:当前行
    • UNBOUNDED:起点

    时间函数:

    data_add()时间加day
    data_sub()时间减day

    数据缺失值处理办法;

    删除样本或删除字段
    用中位数、平均值、众数等填充
    插补:同类均值插补、多重插补、极大似然估计
    

    用其它字段构建模型,预测该字段的值,从而填充缺失值(注意:如果该字段也是用于预测模型中作为特征,那么用其它字段建模填充缺失值的方式,并没有给最终的预测模型引入新信息)

    hash join

    oracle,postgresql它们都是支持hash-join的,mysql并不支持
    hash join是一种数据库在进行多表连接时的处理算法,对于多表连接还有两种比较常用的方式:sort merge-join 和 nested loop。

    hash-join就算讲两表中的小表(称S)作为hash表,然后去扫描另一个表(称M)的每一行数据,用得出来的行数据根据连接条件去映射建立的hash表,hash表是放在内存中的,这样可以很快的得到对应的S表与M表相匹配的行。

    hash-join只适用于等值连接,对于>, <, <=, >=这样的查询连接还是需要nested loop这种通用的连接算法来处理。如果连接key本来就是有序的或者需要排序,那么可能用merge-join的代价会比hash-join更小,此时merge-join会更有优势。

    对于结果集很大的情况,merge-join需要对其排序效率并不会很高,而nested loop join是一种嵌套循环的查询方式无疑更不适合大数据集的连接,而hash-join正是为处理这种棘手的查询方式而生,尤其是对于一个大表和一个小表的情况,基本上只需要将大小表扫描一遍就可以得出最终的结果集。

    展开全文
  • 大数据HIVE---进阶

    2019-06-13 22:42:51
    要讲HIVE进阶,窗口函数不得不提,作者之前的文章《Hive窗口函数进阶指南》已经很详细地讲解了这部分内容,为了省去大家点链接跳来跳去的麻烦,下面将其核心内容摘录出来,如下所示。 窗口函数也称为OLAP...

    本位主要讲解大数据分析师在工作中需要用到的HIVE进阶知识,主要包括:

    窗口函数
    数据倾斜
    性能调优
    explain
    替换引擎

    那,就直接开讲了。

    窗口函数

    要讲HIVE进阶,窗口函数不得不提,作者之前的文章《Hive窗口函数进阶指南》已经很详细地讲解了这部分内容,为了省去大家点链接跳来跳去的麻烦,下面将其核心内容摘录出来,如下所示。

    窗口函数也称为OLAP(OnlineAnalytical Processing)函数,是对一组值进行操作,不需要使用Group by子句对数据进行分组,还能在同一行返回原来行的列和使用聚合函数得到的聚合列。

    SQL语法
    在这里插入图片描述
    如上代码所示,窗口函数的语法分为四个部分:

    函数子句:指明具体操作,如sum-求和,first_value-取第一个值;

    partition by子句:指明分区字段,如果没有,则将所有数据作为一个分区;

    order by子句:指明了每个分区排序的字段和方式,也是可选的,没有就是按照表中的默认顺序;

    窗口子句:指明相对当前记录的计算范围,可以向上(preceding),可以向下(following),也可以使用between指明,上下边界的值,没有的话默认为当前分区。有些场景比较特殊,后文会讲到这种场景。

    分类

    按照窗口函数的功能分为:计算、取值、排序、序列四种

    在这里插入图片描述
    使用场景

    结合实际场景看看怎么用窗口函数来解决问题。下面针对不同的使用场景,将窗口函数的使用呈现给大家。

    所有例子的数据均来自下图这张表。
    在这里插入图片描述
    用于辅助计算

    主要的用法是在原有表的基础上,增加一列聚合后的值,辅以后续的计算。

    例如:统计出不同产品类型售价最高的产品。
    具体代码如下:

    –使用窗口函数max
    select a.product_type,a.product_name
    from
    (
    selectproduct_name,product_type,sale_price
    ,max(sale_price) over
    (
    partitionby product_type
    ) as max_sale_price
    –增加一列为聚合后的最高售价
    fromproduct
    ) a
    where a.sale_price = a.max_sale_price;
    –保留与最高售价相同的记录数
    执行结果:
    在这里插入图片描述
    累积计算

    标准聚合函数作为窗口函数配合order by使用,可以实现累积计算。

    例如:sum窗口函数配合order by,可以实现累积和。
    具体代码如下:
    SELECT product_id,product_name
    ,product_type,sale_price
    ,SUM(sale_price) OVER
    (
    ORDER BYproduct_id
    ) AS current_sum
    FROM product;

    执行结果:
    在这里插入图片描述
    相应的AVG窗口函数配合order by,可以实现累积平均,max可以实现累积最大值,min可以实现累积最小值,count则可以实现累积计数。

    注意,只有计算类的窗口函数可以实现累积计算。

    标准聚合函数作为窗口函数使用的时候,在指明order by的情况下,如果没有Window子句,则Window子句默认为:RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW(上边界不限制,下边界到当前行)。

    移动计算

    移动计算是在分区和排序的基础上,对计算范围进一步做出限定。

    例如:按照产品ID排序,将最近3条的销售价格进行汇总平均。
    具体代码如下:
    SELECT product_id,product_name
    ,sale_price
    ,AVG(sale_price)
    over
    (
    ORDER BY product_id
    rows 2 preceding
    ) AS moving_avg
    FROM product;

    rows 2 preceding的意思就是“截止到之前2行”。也就是将作为汇总对象的记录限定为如下的最靠近的3行。

    执行结果如下:
    在这里插入图片描述
    取一字段值

    取值的窗口函数有:first_value/last_value、lag/lead。

    first_value(字段名)-取出分区中的第一条记录的任意一个字段的值,可以排序也可以不排序,此处也可以进一步指明Window子句。

    lag(字段名,N,默认值)-取出当前行之上的第N条记录的任意一个字段的值,这里的N和默认值都是可选的,默认N为1,默认值为null。

    使用first_value取出每个分类下的最贵的产品,如下:

    select distinct product_type
    ,first_value(product_name) over
    (partition by product_type
    order by sale_price desc) as max_price_product
    from product

    执行结果如下:
    在这里插入图片描述
    排序

    排序对应的四个窗口函数为:rank、dense_rank、row_number、ntitle

    rank:计算排序时,如果存在相同位次的记录,则会跳过之后的位次。
    e.g. 有三条记录排在第1位时:1位、1位、1位、4位…

    dense_rank:计算排序时,即使存在相同位次的记录,也不会跳过之后的位次。
    e.g. 有三条记录排在第1位时:1位、1位、1位、2位…

    row_number:赋予唯一的连续位次。
    e.g. 有三条记录排在第1位时:1位、2位、3位、4位…

    ntitle:用于将分组数据按照顺序切分成n片,返回当前切片值
    e.g. 对于一组数字(1,2,3,4,5,6),ntile(2)切片后为(1,1,1,2,2,2)

    1)统计所有产品的售价排名

    具体代码如下:
    SELECT product_name,product_type
    ,sale_price,
    RANK () OVER
    (
    ORDER BY sale_price
    ) AS ranking
    FROM product;

    执行结果如下:
    在这里插入图片描述
    2)统计各产品类型下各产品的售价排名

    具体代码如下:
    SELECT product_name,product_type
    ,sale_price,
    RANK () OVER
    (
    PARTITION BY product_type
    ORDER BY sale_price
    ) AS ranking
    FROM product;

    执行结果如下:
    在这里插入图片描述
    对比一下dense_rank、row_number、ntile

    具体代码如下:
    SELECT product_name,product_type,sale_price,
    RANK ()OVER (ORDER BY sale_price) AS ranking,
    DENSE_RANK () OVER (ORDER BY sale_price) AS dense_ranking,
    ROW_NUMBER () OVER (ORDER BY sale_price) AS row_num,
    ntile(3)OVER (ORDER BY sale_price) as nt1,
    ntile(30)OVER (ORDER BY sale_price) as nt2
    –切片大于总记录数
    FROM product;

    执行结果如下:
    在这里插入图片描述
    从结果可以发现,当ntile(30)中的切片大于了总记录数时,切片的值为记录的序号。

    序列

    序列中的两个窗口函数cume_dist和percent_rank,通过实例来看看它们是怎么使用的。

    1)统计小于等于当前售价的产品数,所占总产品数的比例

    具体代码如下:
    SELECT product_type,product_name,sale_price,
    CUME_DIST() OVER(ORDER BY sale_price) AS rn1,
    CUME_DIST() OVER
    (
    PARTITIONBY product_type
    ORDER BYsale_price
    ) AS rn2
    FROM product;

    执行结果如下:
    在这里插入图片描述
    rn1: 没有partition,所有数据均为1组,总行数为8,
    第一行:小于等于100的行数为1,因此,1/8=0.125
    第二行:小于等于500的行数为3,因此,3/8=0.375
    rn2: 按照产品类型分组,product_type=厨房用品的行数为4,
    第三行:小于等于500的行数为1,因此,1/4=0.25

    2)统计每个产品的百分比排序

    当前行的RANK值-1/分组内总行数-1
    具体代码如下:
    SELECT product_type,product_name,sale_price,
    percent_rank() OVER (ORDER BY sale_price) AS rn1,
    percent_rank() OVER
    (
    PARTITIONBY product_type
    ORDER BYsale_price
    ) AS rn2
    FROM product;

    执行结果如下:
    在这里插入图片描述
    rn1: 没有partition,所有数据均为1组,总行数为8,
    第一行:排序为1,因此,(1-1)/(8-1)= 0
    第二行:排序为2,因此,(2-1)/(8-1)= 0.14
    rn2: 按照产品类型分组,product_type=厨房用品的行数为4,
    第三行:排序为1,因此,(1-1)/(4-1)= 0
    第四行:排序为1,因此,(2-1)/(4-1)= 0.33

    数据倾斜

    什么是数据倾斜

    数据倾斜就是数据的分布不平衡,某些地方特别多,某些地方又特别少,导致在处理数据的时候,有些很快就处理完了,而有些又迟迟未能处理完,导致整体任务最终迟迟无法完成,这种现象就是数据倾斜。

    针对mapreduce的过程来说主要表现是:任务进度长时间维持在 99%或者 100%的附近,查看任务监控页面,发现只有少量 reduce 子任务未完成,因为其处理的数据量和其他的 reduce 差异过大。单一 reduce 处理的记录数和平均记录数相差太大,通常达到好几倍之多,最长时间远大于平均时长。

    哪些操作容易造成数据倾斜?
    在这里插入图片描述
    产生数据倾斜的原因

    结合数据倾斜的场景,可以总结出产生数据倾斜的原因

    1. key 分布不均匀
    2. 业务数据本身的特性
    3. 建表考虑不周全,如partition的数量过少
    4. 某些 HQL 语句本身就容易产生数据倾斜,如join

    优化方法

    既然已经知道了哪些情况可能会产生数据倾斜以及产生数据倾斜的原因,那么如何去规避数据倾斜问题呢?

    下面结合具体的场景来说说

    特殊值产生的数据倾斜

    在日志中,常会有字段值丢失的问题,比如日志中的 user_id,如果取其中的 user_id 和用户表中的 user_id 相关联,就会碰到数据倾斜的问题。

    解决方案 1:user_id 为空的不参与关联
    select *
    from log a join user b
    on a.user_id is not null and a.user_id = b.user_id
    union all
    select *
    from log c
    where c.user_id is null;

    解决方案 2:赋予空值新的 key 值
    select *
    from log a left outer join user b
    on case when a.user_id is null thenconcat(‘null_’,rand()) else a.user_id end = b.user_id

    方法 2 比方法 1 效率更好,不但 IO 少了,而且作业数也少了。

    方案 1 中,log 表 读了两次,job数肯定是 2,而方案 2 job数是 1。
    方法 2 使本身为 null 的所有记录不会拥挤在同一个 reduceTask 了,加上随机字符串值,会分散到了多个 reduceTask 中,由于 null 值关联不上,处理后并不影响最终结果。

    大小表关联查询产生数据倾斜

    对于这种数据倾斜一般的做法是使用MapJoin-将其中做连接的小表(全量数据)分发到所有 MapTask 端进行 Join,从而避免了 reduceTask,前提要求是内存足以装下该全量数据。

    以大表 a 和小表 b 为例,所有的 maptask 节点都装载小表 b 的所有数据,然后大表 a 的 一个数据块数据比如说是 a1 去跟 b 全量数据做链接,就省去了 reduce 做汇总的过程。

    所以相对来说,在内存允许的条件下使用 map join 比直接使用 MapReduce 效率还高些, 当然这只限于做 join 查询的时候。

    其实对于多表join,是否开启MapJoin,可以进行设置的,具体参数如下:

    set hive.auto.convert.join=true; //设置 MapJoin 优化自动开启
    set hive.mapjoin.smalltable.filesize=25000000 //设置小表不超过多大时开启 mapjoin 优化

    也可以人为指定开启MapJoin,请看下面的代码:
    select /* +mapjoin(b) */ a.id aid, name, age
    from a join b
    on a.id = b.id;

    因为加了/* +mapjoin(b) */这一段代码,执行的时候就会将b表读入内存中,但是要求b表必须是小表,数据量不能太大。

    性能调优

    由于Hive的执行依赖于底层的MapReduce作业,因此对MapReduce作业的调整优化是提高Hive性能的基础。所以可以从以下几个方面进行一系列的调优,来大幅度地提高Hive的查询性能。

    启用压缩

    在Hive中对中间数据或最终数据做压缩,是提高数据吞吐量和性能的一种手段。对数据做压缩,可以大量减少磁盘的存储空间,比如基于文本的数据文件,可以将文件压缩40%或更多。同时压缩后的文件在网络间传输I/O也会大大减少;当然压缩和解压缩也会带来额外的CPU开销,但是却可以节省更多的I/O和使用更少的内存开销。

    常见的压缩方式有:GZIP、BZIP2、LZO、Snappy等。

    那这么多种压缩方式,使用哪一种呢?可以通过压缩比、压缩速度、是否可分割来决定选哪一种,压缩比和压缩速度都好理解,是否可分割是指压缩后的文件是否可以再分割:可以分割的格式允许单一文件由多个Mapper程序同时读取,可以做到更好的并行化。

    下表是各种压缩方式的对比:
    在这里插入图片描述
    如何设置

    前文有提到在Hive中对中间数据或最终数据做压缩,那分别来看看如何设置。
    中间数据压缩
    set hive.exec.compress.intermediate=true
    set mapred.map.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec

    hive.exec.compress.intermediate:默认该值为false,设置为true为激活中间数据压缩功能。HiveQL语句最终会被编译成Hadoop的Mapreduce job,开启Hive的中间数据压缩功能,就是在MapReduce的shuffle阶段对mapper产生的中间结果数据压缩。在这个阶段,优先选择一个低CPU开销的算法。

    mapred.map.output.compression.codec:该参数是具体的压缩算法实现类的配置参数,SnappyCodec是比较适合这种场景的编解码器,该算法会带来很好的压缩比和较低的CPU开销。

    最终数据压缩

    set hive.exec.compress.output=true
    setmapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec
    hive.exec.compress.output:该参数控制最终数据压缩的激活与禁用,设置为true来声明将结果文件进行压缩。
    mapred.output.compression.codec:选择一个合适的编解码器,如选择SnappyCodec。

    避免全局排序

    Hive中使用order by子句实现全局排序。order by只用一个Reducer产生结果,对于大数据集,这种做法效率很低。

    如果不需要全局有序,则可以使用sort by子句,该子句为每个reducer生成一个排好序的文件。如果需要控制一个特定数据行流向哪个reducer,可以使用distribute by子句,例如:
    select id, name, salary, dept
    from employee
    distribute by dept
    sort by id asc, name desc;

    属于一个dept的数据会分配到同一个reducer进行处理,同一个dept的所有记录按照id、name列排序。最终的结果集是局部有序的。

    优化limit操作

    默认时limit操作仍然会执行整个查询,然后返回限定的行数。在有些情况下这种处理方式很浪费,因此可以通过设置下面的属性避免此行为。
    在这里插入图片描述
    说明:
    hive.limit.optimize.enable:是否启用limit优化。当使用limit语句时,对源数据进行抽样。
    hive.limit.row.max.size:在使用limit做数据的子集查询时保证的最小行数据量。
    hive.limit.optimize.limit.file:在使用limit做数据子集查询时,采样的最大文件数。
    hive.limit.optimize.fetch.max:使用简单limit数据抽样时,允许的最大行数。

    启用并行

    每条HiveQL语句都被转化成一个或多个执行阶段,可能是一个MapReduce阶段、采样阶段、归并阶段、限制阶段等。默认时,Hive在任意时刻只能执行其中一个阶段。

    如果组成一个特定作业的多个执行阶段是彼此独立的,那么它们可以并行执行,从而整个作业得以更快完成。通过设置下面的属性启用并行执行。
    在这里插入图片描述
    说明:
    hive.exec.parallel:是否并行执行作业。
    hive.exec.parallel.thread.number:最多可以并行执行的作业数。

    启用MapReduce严格模式

    Hive提供了一个严格模式,可以防止用户执行那些可能产生负面影响的查询。通过设置下面的属性启用MapReduce严格模式。
    在这里插入图片描述
    严格模式禁止3种类型的查询:

    1)对于分区表,where子句中不包含分区字段过滤条件的查询语句不允许执行。
    2)对于使用了order by子句的查询,要求必须使用limit子句,否则不允许执行。
    3)限制笛卡尔积查询。

    控制并行Reduce任务

    Hive通过将查询划分成一个或多个MapReduce任务达到并行的目的。确定最佳的mapper个数和reducer个数取决于多个变量,例如输入的数据量以及对这些数据执行的操作类型等。

    如果有太多的mapper或reducer任务,会导致启动、调度和运行作业过程中产生过多的开销,而如果设置的数量太少,那么就可能没有充分利用好集群内在的并行性。对于一个Hive查询,可以设置下面的属性来控制并行reduce任务的个数。
    在这里插入图片描述
    说明:
    hive.exec.reducers.bytes.per.reducer:每个reducer的字节数,默认值为256MB。Hive是按照输入的数据量大小来确定reducer个数的。例如,如果输入的数据是1GB,将 使用4个reducer。
    hive.exec.reducers.max:将会使用的最大reducer个数。

    启用向量化

    向量化特性在Hive 0.13.1版本中被首次引入。通过查询执行向量化,使Hive从单行处理数据改为批量处理方式,具体来说是一次处理1024行而不是原来的每次只处理一行,这大大提升了指令流水线和缓存的利用率,从而提高了表扫描、聚合、过滤和连接等操作的性能。可以设置下面的属性启用查询执行向量化。
    在这里插入图片描述
    说明:
    hive.vectorized.execution.enabled:如果该标志设置为true,则开启查询执行的向量模式,默认值为false。

    hive.vectorized.execution.reduce.enabled:如果该标志设置为true,则开启查询执行reduce端的向量模式,默认值为true。

    hive.vectorized.execution.reduce.groupby.enabled:如果该标志设置为true,则开启查询执行reduce端groupby操作的向量模式,默认值为true。

    启用基于成本的优化器

    Hive 0.14版本开始提供基于成本优化器(CBO)特性。使用过Oracle数据库的读者对CBO一定不会陌生。与Oracle类似,Hive的CBO也可以根据查询成本制定执行计划,例如确定表连接的顺序、以何种方式执行连接、使用的并行度等。设置下面的属性启用基于成本优化器。
    在这里插入图片描述
    说明:
    hive.cbo.enable:控制是否启用基于成本的优化器,默认值是true。Hive的CBO使用Apache Calcite框架实现。

    hive.compute.query.using.stats:该属性的默认值为false。如果设置为true,Hive在执行某些查询时,例如select count(1),只利用元数据存储中保存的状态信息返回结果。 为了收集基本状态信息,需要将hive.stats.autogather属性配置为true。为了收集更多的状态信息,需要运行analyze table查询命令,例如下面的语句收集sales_order_fact表的统计信息。

    analyze table
    sales_order_fact compute statistics
    for
    columns;

    hive.stats.fetch.partition.stats:该属性的默认值为true。操作树中所标识的统计信息,需要分区级别的基本统计,如每个分区的行数、数据量大小和文件大小等。分区统计信息从元数据存储中获取。如果存在很多分区,要为每个分区收集统计信息可能会消耗大量的资源。这个标志可被用于禁止从元数据存储中获取分区统计。当该标志设置为false时,Hive从文件系统获取文件大小,并根据表结构估算行数。

    hive.stats.fetch.column.stats:该属性的默认值为false。操作树中所标识的统计信息,需要列统计。列统计信息从元数据存储中获取。如果存在很多列,要为每个列收 集统计信息可能会消耗大量的资源。这个标志可被用于禁止从元数据存储中获取列统计。

    EXPLAIN

    explain-解释计划,通过explain命令可以知道hive将会如何执行所写的查询语句,需要注意的是查询语句并没有执行哦,只是告诉你将会怎么样执行。

    这对于HIVE SQL的调优是很重要的,一个复杂的SQL如果执行的时间过长,可以根据解释计划来看具体执行的步骤,进而找到可以优化的地方。

    下面就结合例子看看如何查看解释计划,代码中的注释部分是要重点关注的。

    EXPLAIN
    select student,sum(score)
    FROM test.class
    GROUP BY student

    执行上述的代码:

    Explain
    Plan optimized by CBO.
    –CBO是打开的,计划基于CBO优化

    Vertex dependency in root stage
    Reducer 2 <- Map 1 (SIMPLE_EDGE)
    –简单的依赖关系,一个Map2个Reducer

    Stage-0
    Fetch Operator
    limit:-1
    Stage-1
    Reducer 2
    File Output Operator [FS_6]
    Group By Operator[GBY_4] (rows=9 width=16) --reducer端的聚合
    Output:["_col0","_col1"],aggregations:[“sum(VALUE._col0)”],keys:KEY._col0
    <-Map 1 [SIMPLE_EDGE]//发生在job的 map 处理阶段过程
    SHUFFLE [RS_3]
    PartitionCols:_col0
    Group ByOperator [GBY_2] (rows=18 width=16) --map端的聚合
    Output:["_col0","_col1"],aggregations:[“sum(score)”],keys:student
    Select Operator [SEL_1] (rows=18 width=16)
    Output:[“student”,“score”]
    TableScan [TS_0] (rows=18 width=16) --读取表的数据
    test@class,class,Tbl:COMPLETE,Col:NONE,Output:[“student”,“score”]

    上述打印的就是解释计划,主要关注的是Stage部分,需要注意的是这一部分是从下往上进行查看的,最先查看到的是读取表的数据(18条记录)及选取的字段,然后可以看出在Map端先做了一次聚合,然后在recucer端又进行了一次聚合。

    EXPLAIN后面可以加不同关键字来针对性的查看,DEPENDENCY|AUTHORIZATION在实际工作中比较常用,我们着重介绍下这两个关键字。

    DEPENDENCY

    EXPLAIN DEPENDENCY
    select *
    FROM test.test_view --是一个测试视图

    Explain
    {“input_tables”:[{“tablename”:“test@test_view”,“tabletype”:“VIRTUAL_VIEW”},{“tablename”:“test@product”,“tabletype”:“MANAGED_TABLE”,“tableParents”:"[test@test_view]"}],“input_partitions”:[]}

    在这里插入图片描述
    EXPLAIN DEPENDENCY用于描述整个sql需要依赖的输入数据,为了直观的看出它的结构,我将输出的JSON格式化后展开如上图所示:分为两部分input_tables和input_partitions,顾名思义就是输入的表和分区, 实际运用场景:

    1)排错,排查某个程序可能在运行过程略过了某个分区
    2)理清程序依赖的表的输入,理解程序的运行,特别是理解在俩表join的情况下的依赖输入
    3)查看视图的实际数据来源

    AUTHORIZATION

    Explain
    INPUTS:
    test@class
    OUTPUTS:
    hdfs://hans/tmp/hive/spark/da7f94b3-b9e2-46f1-8bee-8a367f62a753/hive_2019-05-30_10-58-00_447_6351031319937169270-1/-mr-10001
    CURRENT_USER:
    spark
    OPERATION:
    QUERY
    AUTHORIZATION_FAILURES:
    Permission denied: Principal [name=spark,type=USER] does not have following privileges for operation QUERY [[SELECT] onObject [type=TABLE_OR_VIEW, name=test.class]]

    用来表达CURRENT_USER的用户对哪些INPUTS有读操作,对哪些OUTPUTS有写操作。

    上面的解释计划是spark的用户,读取test@class的数据,查询出来的结果会暂时存放到hdfs://hans/tmp/hive/spark/da7f94b3-b9e2-46f1-8bee-8a367f62a753/hive_2019-05-30_10-58-00_447_6351031319937169270-1/-mr-10001文件中。

    替换引擎

    为什么要替换

    HIVE的默认执行引擎是MapReduce,MapReduce是一种离线计算框架,将一个算法抽象成Map和Reduce两个阶段进行处理,每个阶段都是用键值对(key/value)作为输入和输出,非常适合数据密集型计算。

    但是缺点也很明显,最直观的感受就是执行时间长,它在计算时会对磁盘进行多次的读写操作,这样启动多轮job的代价略有些大,不仅占用资源,更耗费大量的时间。

    本篇前面在性能调优部分,所讲解的优化措施就是针对MapReduce的,如果现在有另外一个引擎可以代替MapReduce并且自带优化策略,你换不换?

    替换成什么?

    目前的主流选择是Tez,Tez是Apache开源的支持DAG作业的计算框架,它直接源于MapReduce框架,核心思想是将Map和Reduce两个操作进一步拆分,即Map被拆分成Input、Processor、Sort、Merge和Output, Reduce被拆分成Input、Shuffle、Sort、Merge、Processor和Output等,这样,这些分解后的元操作可以任意灵活组合,产生新的操作,这些操作经过一些控制程序组装后,可形成一个大的DAG作业。

    总结起来,Tez在执行绩效上有以下特点:

    (1)比MapReduce更好的性能提升
    (2)最佳资源管理
    (3)运行中重新配置计划
    (4)动态物理数据流决策

    从上面Tez的介绍来看,Tez的确有很多优点。

    下面我们单单从执行过程来看,传统的MR(包括Hive,Pig和直接编写MR程序),假设有四个有依赖关系的MR作业(1个较为复杂的Hive SQL语句或者Pig脚本可能被翻译成4个有依赖关系的MR作业),运行过程如下(其中,绿色是Reduce Task,需要写HDFS;云状表示写屏蔽(write barrier,一种内核机制,持久写);绿色的圆圈代表一个job):
    在这里插入图片描述
    MR需要4个job来完成计算,而Tez可以将多个有依赖的作业转换为一个作业(这样只需写一次HDFS,且中间节点较少),从而大大提升DAG作业的性能。

    怎么替换

    肯定是要先安装起来,这里就不具体说明怎么安装了,网上相关的文章很多。安装好了之后,只需对hive-site.xml中修改如下配置:
    在这里插入图片描述

    看到这里,大家可以去查看下自己的工作或者学习的HIVE平台的引擎是什么,如何还是mr建议换掉,在hive的命令行输入下面的代码,即可查看。
    set hive.execution.engine;

    总结

    本篇HIVE进阶讲述的内容,可能在实际工作中不是全部很常用,但是对于更高效的利用HIVE、写出高效和简洁的HIVE SQL代码、程序调错调优是非常重要的,所以掌握这些知识无疑是提升工作效率的一剂良药。

    参考文献:

    [1] 比MR至少快5倍的神器,竟然是它,作者:巩传捷@中兴大数据 -https://www.sohu.com/a/131167936_465944

    [2] MapReduce和Tez对比,作者:凌度 - https://www.cnblogs.com/linn/p/5325147.html

    [3] 数据倾斜及处理,作者:火山Vol -https://www.jianshu.com/p/42be5ca8b11d

    [4] Hive学习之路 (十九)Hive的数据倾斜,作者:扎心了,老铁 - https://www.cnblogs.com/qingyunzong/p/8847597.html

    [5] Hive压缩设置,作者:djd已经存在 - https://blog.csdn.net/djd1234567/article/details/51581354

    [6] Hive的Explain命令,作者:skyl夜 -https://www.cnblogs.com/skyl/p/4737411.html

    [7] Tez官网 - http://tez.apache.org/

    转载至:人工智能与大数据群

    展开全文
  • hive面试题总结(2020最新版)

    千次阅读 多人点赞 2020-03-27 15:05:23
    本文目录一、hive架构相关二、hive的特点三、内部表和外部表的区别?四、4个by的区别?五、介绍一下有哪些常用函数?5.1、行转列函数5.2、列转行函数5.3、...七、hive怎么解决数据倾斜?八、hive优化相关面试题 一...
  • 7. Hive

    2021-04-16 10:10:21
    7.2 Hive 和数据库的区别7.3 Hive 架构7.4 内部表和外部表7.5 排序的区别7.6 窗口函数7.7 Hive 优化7.7.1. Map Join7.7.2. 行列过滤7.7.3. group by 去重7.7.4. 数据倾斜1. 数据倾斜原因2. 调整 Map 数3. 调整 ...
  • 本文为《大数据分析师入门课程》系列的第6篇,主要讲解大数据分析师在工作中需要用到的HIVE进阶知识,主要包括:窗口函数数据倾斜性能调优explain替换引擎那,就直接开讲了。窗口函数要讲...
  • 本文为《大数据分析师入门课程》系列的第6篇,主要讲解大数据分析师在工作中需要用到的HIVE进阶知识,主要包括:窗口函数数据倾斜性能调优explain替换引擎那,就直接开...

空空如也

空空如也

1 2
收藏数 36
精华内容 14
关键字:

hive窗口函数数据倾斜