zoukankan      html  css  js  c++  java
  • HIVE高级(10):优化(10) HQL 语法优化(1) 单表优化

    1 列裁剪与分区裁剪

      列裁剪就是在查询时只读取需要的列,分区裁剪就是只读取需要的分区。当列很多或者数据量很大时,如果 select * 或者不指定分区,全列扫描和全表扫描效率都很低。
      Hive 在读数据的时候,可以只读取查询中所需要用到的列,而忽略其他的列。这样做可以节省读取开销:中间表存储开销和数据整合开销。

    2 Group By

      默认情况下,Map 阶段同一 Key 数据分发给一个 Reduce,当一个 key 数据过大时就倾斜了。
    并不是所有的聚合操作都需要在 Reduce 端完成,很多聚合操作都可以先在 Map 端进行部分聚合,最后在 Reduce 端得出最终结果。 
    开启 Map 端聚合参数设置
    (1)是否在 Map 端进行聚合,默认为 True
    set hive.map.aggr = true;
    (2)在 Map 端进行聚合操作的条目数目
    set hive.groupby.mapaggr.checkinterval = 100000;
    (3)有数据倾斜的时候进行负载均衡(默认是 false)
    set hive.groupby.skewindata = true;
    当选项设定为 true,生成的查询计划会有两个 MR Job。 
      第一个 MR Job 中,Map 的输出结果会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce中,从而达到负载均衡的目的;
      第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作(虽然
    能解决数据倾斜,但是不能让运行速度的更快)。
    hive (default)> select deptno from emp group by deptno;
    Stage-Stage-1: Map: 1 Reduce: 5 Cumulative CPU: 23.68 sec HDFS Read: 
    19987 HDFS Write: 9 SUCCESS
    Total MapReduce CPU Time Spent: 23 seconds 680 msec
    OK
    deptno
    10
    20
    30
    优化以后 
    hive (default)> set hive.groupby.skewindata = true;
    hive (default)> select deptno from emp group by deptno;
    Stage-Stage-1: Map: 1 Reduce: 5 Cumulative CPU: 28.53 sec HDFS Read: 
    18209 HDFS Write: 534 SUCCESS
    Stage-Stage-2: Map: 1 Reduce: 5 Cumulative CPU: 38.32 sec HDFS Read: 
    15014 HDFS Write: 9 SUCCESS
    Total MapReduce CPU Time Spent: 1 minutes 6 seconds 850 msec
    OK
    deptno
    10
    20
    30

    3 Vectorization

    vectorization : 矢量计算的技术,在计算类似scan, filter, aggregation的时候,vectorization技术以设置批处理的增量大小为 1024 行单次来达到比单条记录单次获得更高的效率。
    set hive.vectorized.execution.enabled = true;
    set hive.vectorized.execution.reduce.enabled = true;

    4 Count(Distinct) 去重统计

      数据量小的时候无所谓,数据量大的情况下,由于 COUNT DISTINCT 操作需要用一个Reduce Task 来完成,这一个 Reduce 需要处理的数据量太大,就会导致整个 Job 很难完成,
    一般 COUNT DISTINCT 使用先 GROUP BY 再 COUNT 的方式替换,但是需要注意 group by 造成的数据倾斜问题.
    1)案例实操
    (1)创建一张大表
    hive (default)> create table bigtable(id bigint, time bigint, uid string, 
    keyword
    string, url_rank int, click_num int, click_url string) row format 
    delimited
    fields terminated by '	';
    (2)加载数据 
    hive (default)> load data local inpath '/opt/module/data/bigtable' into table bigtable;
    (3)设置 5 个 reduce 个数
    set mapreduce.job.reduces = 5;
    (4)执行去重 id 查询 
    复制代码
    hive (default)> select count(distinct id) from bigtable;
    Stage-Stage-1: Map: 1 Reduce: 1 Cumulative CPU: 7.12 sec HDFS Read: 
    120741990 HDFS Write: 7 SUCCESS
    Total MapReduce CPU Time Spent: 7 seconds 120 msec
    OK
    c0
    100001
    Time taken: 23.607 seconds, Fetched: 1 row(s)
    复制代码
    (5)采用 GROUP by 去重 id
    复制代码
    hive (default)> select count(id) from (select id from bigtable group by 
    id) a;
    Stage-Stage-1: Map: 1 Reduce: 5 Cumulative CPU: 17.53 sec HDFS Read: 
    120752703 HDFS Write: 580 SUCCESS
    Stage-Stage-2: Map: 1 Reduce: 1 Cumulative CPU: 4.29 sec2 HDFS Read: 
    9409 HDFS Write: 7 SUCCESS
    Total MapReduce CPU Time Spent: 21 seconds 820 msec
    OK
    _c0
    100001
    Time taken: 50.795 seconds, Fetched: 1 row(s)
    复制代码
    虽然会多用一个 Job 来完成,但在数据量大的情况下,这个绝对是值得的。

    5 多重模式

    如果你碰到一堆 SQL,并且这一堆 SQL 的模式还一样。都是从同一个表进行扫描,做不同的逻辑。有可优化的地方:如果有 n 条 SQL,每个 SQL 执行都会扫描一次这张表。 
    insert .... select id,name,sex, age from student where age > 17;
    insert .... select id,name,sex, age from student where age > 18;
    insert .... select id,name,sex, age from student where age > 19;
    -- 隐藏了一个问题:这种类型的 SQL 有多少个,那么最终。这张表就被全表扫描了多少次
    insert int t_ptn partition(city=A). select id,name,sex, age from student 
    where city= A;
    insert int t_ptn partition(city=B). select id,name,sex, age from student 
    where city= B;
    insert int t_ptn partition(city=c). select id,name,sex, age from student 
    where city= c;
    
    修改为:
    from student
    insert int t_ptn partition(city=A) select id,name,sex, age where city= A
    insert int t_ptn partition(city=B) select id,name,sex, age where city= B
    如果一个 HQL 底层要执行 10 个 Job,那么能优化成 8 个一般来说,肯定能有所提高,多重插入就是一个非常实用的技能。一次读取,多次插入,有些场景是从一张表读取数据后,要多次利用。

    6 in/exists 语句

    在 Hive 的早期版本中,in/exists 语法是不被支持的,但是从 hive-0.8x 以后就开始支持这个语法。但是不推荐使用这个语法。虽然经过测验,Hive-2.3.6 也支持 in/exists 操作,但还是推荐使用 Hive 的一个高效替代方案:left semi join 
    比如说:-- in / exists 实现
    select a.id, a.name from a where a.id in (select b.id from b);
    select a.id, a.name from a where exists (select id from b where a.id = 
    b.id);
    可以使用 join 来改写:
    select a.id, a.name from a join b on a.id = b.id;
    应该转换成:
    -- left semi join 实现
    select a.id, a.name from a left semi join b on a.id = b.id;

    本文来自博客园,作者:秋华,转载请注明原文链接:https://www.cnblogs.com/qiu-hua/p/15143780.html

  • 相关阅读:
    HashMap的实现原理
    LinkedHashMap的实现讲解
    ConcurrentHashMap原理分析
    javax.mail Java Extension(扩展)
    Singleton 单例模式
    Java序列化与反序列化(实践)
    Java IO操作
    Java NIO与IO的区别和比较
    java模拟异步消息的发送与回调
    java如何实现多个线程并发运行
  • 原文地址:https://www.cnblogs.com/qiu-hua/p/15143780.html
Copyright © 2011-2022 走看看