小表、大表Join

将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率;再进一步,可以使用map join让小的维度表(1000条以下的记录条数)先进内存。在map端完成reduce。
实际测试发现:新版的hive已经对小表JOIN大表和大表JOIN小表进行了优化。小表放在左边和右边已经没有明显区别。
案例实操

需求

测试大表JOIN小表和小表JOIN大表的效率

建大表、小表和JOIN后表的语句

// 创建大表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 '\t';// 创建小表create table smalltable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';// 创建join后表的语句create table jointable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';

分别向大表和小表中导入数据

hive (default)> load data local inpath '/opt/module/datas/bigtable' into table bigtable;hive (default)>load data local inpath '/opt/module/datas/smalltable' into table smalltable;

关闭mapjoin功能(默认是打开的)

set hive.auto.convert.join = false;

执行小表JOIN大表语句

insert overwrite table jointableselect b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlfrom smalltable sleft join bigtable bon b.id = s.id;Time taken: 35.921 secondsNo rows affected (44.456 seconds)

执行大表JOIN小表语句

insert overwrite table jointableselect b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlfrom bigtable bleft join smalltable son s.id = b.id;Time taken: 34.196 secondsNo rows affected (26.287 seconds)

大表Join大表

空KEY过滤

有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的reducer上,从而导致内存不够。此时我们应该仔细分析这些异常的key,很多情况下,这些key对应的数据是异常数据,我们需要在SQL语句中进行过滤。例如key对应的字段为空,操作如下:
案例实操

配置历史服务器

配置mapred-site.xml
<property><name>mapreduce.jobhistory.addressname><value>hadoop102:10020value>property><property><name>mapreduce.jobhistory.webapp.addressname><value>hadoop102:19888value>property>

启动历史服务器

sbin/mr-jobhistory-daemon.sh start historyserver

查看jobhistory http://hadoop102:19888/jobhistory

创建原始数据表、空id表、合并后数据表

// 创建原始表create table ori(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';// 创建空id表create table nullidtable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';// 创建join后表的语句create table jointable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';

分别加载原始数据和空id数据到对应表中

hive (default)> load data local inpath '/opt/module/datas/ori' into table ori;hive (default)> load data local inpath '/opt/module/datas/nullid' into table nullidtable;

测试不过滤空id

hive (default)> insert overwrite table jointable select n.* from nullidtable n left join ori o on n.id = o.id;Time taken: 42.038 secondsTime taken: 37.284 seconds

测试过滤空id

hive (default)> insert overwrite table jointable select n.* from (select * from nullidtable where id is not null ) n left join ori o on n.id = o.id;Time taken: 31.725 secondsTime taken: 28.876 seconds

空key转换

有时虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,此时我们可以表a中key为空的字段赋一个随机的值,使得数据随机均匀地分不到不同的reducer上。例如:
案例实操:
不随机分布空null值:

设置5个reduce个数

set mapreduce.job.reduces = 5;

JOIN两张表

insert overwrite table jointable select n.* from nullidtable n left join ori b on n.id = b.id;

可以看出来,出现了数据倾斜,某些reducer的资源消耗远大于其他reducer。

随机分布空null值

设置5个reduce个数

set mapreduce.job.reduces = 5;

JOIN两张表

insert overwrite table jointableselect n.* from nullidtable n full join ori o oncase when n.id is null then concat('hive', rand()) else n.id end = o.id;

可以看出来,消除了数据倾斜,负载均衡reducer的资源消耗

MapJoin(小表join大表)

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。

开启MapJoin参数设置

设置自动选择Mapjoin

set hive.auto.convert.join = true; 默认为true

大表小表的阈值设置(默认25M一下认为是小表):

set hive.mapjoin.smalltable.filesize=25000000;

MapJoin工作机制

  1. Task A,它是一个Local Task(在客户端本地执行的Task),负责扫描小表b的数据,将其转换成一个HashTable的数据结构,并写入本地的文件中,之后将该文件加载到DistributeCache中。

  2. Task B,该任务是一个没有Reduce的MR,启动MapTasks扫描大表a,在Map阶段,根据a的每一条记录去和DistributeCache中b表对应的HashTable关联,并直接输出结果。

  3. 由于MapJoin没有Reduce,所以由Map直接输出结果文件,有多少个Map Task,就有多少个结果文件。
    案例实操:
    1)开启Mapjoin功能

set hive.auto.convert.join = true; 默认为true

2)执行小表JOIN大表语句

insert overwrite table jointableselect b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlfrom smalltable sjoin bigtable bon s.id = b.id;Time taken: 24.594 seconds

3)执行大表JOIN小表语句

insert overwrite table jointableselect b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_urlfrom bigtable bjoin smalltable son s.id = b.id;Time taken: 24.315 seconds

Group By

默认情况下,Map阶段同一Key数据分发给一个reduce,当一个key数据过大时就倾斜了。
并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。

开启Map端聚合参数设置

  1. 是否在Map端进行聚合,默认为True

set hive.map.aggr = true
  1. 在Map端进行聚合操作的条目数目

set hive.groupby.mapaggr.checkinterval = 100000
  1. 有数据倾斜的时候进行负载均衡(默认是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 SUCCESSTotal MapReduce CPU Time Spent: 23 seconds 680 msecOKdeptno102030优化以后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 SUCCESSStage-Stage-2: Map: 1  Reduce: 5   Cumulative CPU: 38.32 sec   HDFS Read: 15014 HDFS Write: 9 SUCCESSTotal MapReduce CPU Time Spent: 1 minutes 6 seconds 850 msecOKdeptno102030

Count(Distinct) 去重统计

数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT的全聚合操作,即使设定了reduce task个数,set mapred.reduce.tasks=100;hive也只会启动一个reducer。,这就造成一个Reduce处理的数据量太大,导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换:
案例实操

  1. 创建一张大表

hive (default)> create table bigtable(id bigint, time bigint, uid string, keywordstring, url_rank int, click_num int, click_url string) row format delimitedfields terminated by '\t';
  1. 加载数据

hive (default)> load data local inpath '/opt/module/datas/bigtable' into table bigtable;
  1. 设置5个reduce个数

set mapreduce.job.reduces = 5;
  1. 执行去重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 SUCCESSTotal MapReduce CPU Time Spent: 7 seconds 120 msecOKc0100001Time taken: 23.607 seconds, Fetched: 1 row(s)
  1. 采用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 SUCCESSStage-Stage-2: Map: 1 Reduce: 1 Cumulative CPU: 4.29 sec HDFS Read: 9409 HDFS Write: 7 SUCCESSTotal MapReduce CPU Time Spent: 21 seconds 820 msecOK_c0100001Time taken: 50.795 seconds, Fetched: 1 row(s)

虽然会多用一个Job来完成,但在数据量大的情况下,这个绝对是值得的。

笛卡尔积

尽量避免笛卡尔积,join的时候不加on条件,或者无效的on条件,Hive只能使用1个reducer来完成笛卡尔积

行列过滤

列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤,比如:
案例实操:

  1. 测试先关联两张表,再用where条件过滤

hive (default)> select o.id from bigtable bjoin ori o on o.id = b.idwhere o.id <= 10;Time taken: 34.406 seconds, Fetched: 100 row(s)
  1. 通过子查询后,再关联表

hive (default)> select b.id from bigtable bjoin (select id from ori where id <= 10 ) o on b.id = o.id;Time taken: 30.058 seconds, Fetched: 100 row(s)

动态分区调整

关系型数据库中,对分区表Insert数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中,Hive中也提供了类似的机制,即动态分区(Dynamic Partition),只不过,使用Hive的动态分区,需要进行相应的配置。

开启动态分区参数设置

  1. 开启动态分区功能(默认true,开启)

hive.exec.dynamic.partition=true
  1. 设置为非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。)

hive.exec.dynamic.partition.mode=nonstrict
  1. 在所有执行MR的节点上,最大一共可以创建多少个动态分区。默认1000

hive.exec.max.dynamic.partitions=1000
  1. 在每个执行MR的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。

hive.exec.max.dynamic.partitions.pernode=100
  1. 整个MR Job中,最大可以创建多少个HDFS文件。默认100000

hive.exec.max.created.files=100000
  1. 当有空分区生成时,是否抛出异常。一般不需要设置。默认false

hive.error.on.empty.partition=false

案例实操

需求:将dept表中的数据按照地区(loc字段),插入到目标表dept_partition的相应分区中。

  1. 创建目标分区表

hive (default)> create table dept_partition(id int, name string) partitionedby (location int) row format delimited fields terminated by '\t';
  1. 设置动态分区

set hive.exec.dynamic.partition.mode = nonstrict;hive (default)> insert into table dept_partition partition(location) select deptno, dname, loc from dept;
  1. 查看目标分区表的分区情况

hive (default)> show partitions dept_partition;

思考:目标分区表是如何匹配到分区字段的?


简书:https://www.jianshu.com/u/0278602aea1d
CSDN:https://blog.csdn.net/u012387141

hive 两个没有null指定的表左关联的结果有null_Hive企业级调优表的优化相关推荐

  1. hive 两个没有null指定的表左关联的结果有null_《数据仓库篇》——Hive的学习笔记3...

    <数据仓库篇>--Hive的学习笔记1 讲了Hive的原理,<数据仓库篇>--Hive的学习笔记2 讲了Hive的操作,本篇将介绍Hive的优化. 本篇将Hive的优化分成三个 ...

  2. hive 两个没有null指定的表左关联的结果有null_Hive的优化原则

    原文链接:https://zhuanlan.zhihu.com/p/174469951 本篇将 Hive 的优化分成三个部分: 第一部分是 SQL 通用语法优化, 第二部分是针对 Hive 所具有的数 ...

  3. 全方位揭秘!大数据从0到1的完美落地之Hive企业级调优

    Hive企业级调优 调优原则已经在MR优化阶段已经有核心描述,优化Hive可以按照MR的优化思路来执行 优化的主要考虑方面: 环境方面:服务器的配置.容器的配置.环境搭建 具体软件配置参数: 代码级别 ...

  4. 一张表左关联另外两张表,三表关联

    三表连接经常做的都是两两之间关联,尝试了一下两张表同时关联到一张表,结果和预期想的一样,当主表t1关联第二表t2时,t2中不存在与t1的code相等的情况下为null,在t1再关联t3时,t3中不存在 ...

  5. mysql两表左关联_mysql中一张表LEFT JOIN 左关联两张表语句

    先看实例 代码如下 复制代码 SELECT p.price, pd.name, m.manufacturers_name FROM (products p LEFT JOIN products_des ...

  6. MySQL数据库调优————表结构设计优化

    三范式 第一范式 字段具有原子性,即数据库表的每一个字段都是不可分割的原子数据项,不能是集合.数组.记录等非原子数据项 当实体中的每个属性有多个值时,必须拆分为不同的属性 第二范式 满足第一范式的基础 ...

  7. Mybatis-plus:单表使用关联查询+ResultMap结果映射

    Mybatis-plus:单表使用关联查询+ResultMap结果映射 一:数据表与实体类 二:mapper与mapper.xml 三:service 四:控制器 五:返回结果 一:数据表与实体类 数 ...

  8. java get和post请求参数设置,Get和Post两种方式向指定地址提交表单

    做Java做了很多年,却总是把一些东西遗忘,过后再着急的找寻.最近,需要通过Java代码模拟一个表单提交,却怎么也想不起来如何封装数据了. 本篇主要描述Java网络参数传递,主要分为get和post两 ...

  9. 真正让你明白Hive调优系列3:笛卡尔乘积,小表join大表,Mapjoin等问题

    0.Hive中的优化分类    真正想要掌握Hive的优化,要熟悉相关的MapReduce,Yarn,hdfs底层源码,明晰Hive的底层执行流程.真正让你明白Hive调优系列,会征对下面分类逐一分析 ...

最新文章

  1. python 漂亮的excel_python 自定义漂亮的 excel 结果测试报告
  2. Delphi 能不能从Ring 3进入Ring 0
  3. Rancher 2.0正式发布:简化、加速企业Kubernetes落地
  4. 【C++grammar】string类和array类
  5. php mysql query 行数_如何在PHP中获取MYSQL数据库返回的数据的行数?
  6. apache点NET环境
  7. 2020-03-13 MySQL 8 绿色安装
  8. error: Exited sync due to fetch errors
  9. 一个应届计算机毕业生的2012求职之路
  10. protobuf3使用,golang语言实现
  11. vdi linux桌面,ubuntu VDI ( Ulteo Open Virtual Desktop
  12. pandas dataframe query()
  13. ISCC2018 Misc WriteUp
  14. Rescue-Prime hash STARK
  15. proteus8单片机c语言仿真教程,入门学习Proteus 8仿真软件以及C51单片机的LED点亮(C语言)——实例...
  16. Method has too many Body parameters: public abstract java.util.List com.yun.client.DemandClient.que
  17. 百家游坛发起苹果APP推广者大会 揭行业潜规则
  18. [NOIP赛前冲刺第一期]初赛基础知识归纳
  19. HTML2Canvas---合成海报遇到问题总结
  20. Delphi指针样式控件代码

热门文章

  1. 强制类型转换之(==)
  2. Linux裸设备管理详解--
  3. Difference between Win-builds vs MinGW-builds
  4. Kernel那些事儿之内存管理(5) --- 衣带渐宽终不悔(上)
  5. iOS 推送通知详解
  6. A ndroid 获取屏幕高度、标题高度、状态栏高度详解
  7. [分享]屏幕取色工具
  8. java连接mysql数据库 R,java连接MySql数据库!
  9. 我的世界java版gamemode指令_【服务器相关】【求助!】关于服务器中使用gamemode等命令错误。...
  10. 设计模式 可复用面向对象软件的基础_面向对象的可复用设计模式之简单工厂模式(1/24)...