1)没有使用map join
-- a 表是大表,数据量是百万级别 -- b 表是小表,数据量在百级别 select a.field1 as field1, b.field2 as field2, b.field3 as field3 from a left join b on a.field1 = b.field1;
运行时间为:总耗时:08:10:03
2) 使用map join 优化后
-- a 表是大表,数据量是百万级别 -- b 表是小表,数据量在百级别 -- 特别说明:mapjion括号中的b就是指定哪张表为小表 select a.field1 as field1, b.field2 as field2, b.field3 as field3 from a left join b on a.field1 = b.field1;
运行时间为:总耗时:00:12:39
通过对比,map join大大提升了SQL执行效率,节省分析时间
二、map join是如何解决数据小表与大表join优化?
背景说明:A表有百万级、千万级、亿级,B表2万行及2万以内的记录,而且A表中数据倾斜特别严重,有一个key上有30%或40%以上记录,在运行中特别的慢,而且在reduce的过程中遇到内存不够而报错。
这个问题属于典型的小表与join优化问题,考虑使用mapjoin 进行优化
mapjoin的原理: MapJoin 会把小表全部读入内存中,在map阶段直接拿另外一个表的数据和内存中表数据做匹配,由于在map是进行了join *** 作,省去了reduce 阶段,运行的效率就会高很多。
为了更方便理解,mapjoin原理大白话:小表复制到各个节点上,并加载到内存中;大表分片,与小表完成连接 *** 作。
这样就不会由于数据倾斜导致某个reduce上落的数据太多而失败。于是原来的sql 可以通过使用hint 的方式指定join 时使用 mapjoin,示例如下:
select big_table.a, small_table.b from big_table left join small_table on big_table.a = small_table.a;
添加了hint 显示明确将small_table 读入内存中,通过此方式运行的话效率比以前的写法高了很多。
那么问题来了,什么样的表应该被视为小表small_table?
参与连接的小表的行数,以不超过2万条为宜,大小不超过25M.
三、map join原理
Hive 整个过程分为Map、Shuffle、Reduce三大阶段。
简单的说,Hive中的Join 可分为Common Join(Reduce阶段完成join)和 Map Join (Map阶段完成join)。
A、Map阶段读取源表的数据,Map输出时候以Join on条件中的列为key,如果Join有多个关联键,则以这些关联键的组合作为key;Map输出的value 为join之后所关心的(select 或者where 中需要用到的)列;同时在value中还会包含表的Tag信息,用于标明此value对应哪个表;按照key进行排序
B、Shuffle阶段根据key的值进行hash,并将key/value按照hash值推送至不同的reduce中,这样确保两个表中相同的key位于同一个reduce中
C、Reduce阶段根据key的值完成join *** 作,期间通过Tag来识别不同表中的数据。
1)Hive Common Join
如果不指定Map Join或者不符合MapJoin的条件,那么Hive解析器会将Join *** 作转换成Common Join,即:在Reduce阶段完成join. 即:需要通过map、shuffle、reduce三个大的阶段
2)Hive Map Join
2.1 什么是Map Join?
MapJoin 顾名思义,就是在Map阶段进行表之间的连接。而不需要进入到Reduce阶段才进行连接。这样就节省了在Shuffle阶段时要进行的大量数据传输。从而起到了优化作业的作用。
2.2 MapJoin的原理:
通过情况下,要连接的各个表里面的数据会分布在不同的Map中进行处理。即同一个Key对应的Value可能存在不同的Map中。这样就必段等到Reduce中去连接。要使MapJoin能够顺利进行,那就必段满足这样的条件:除了一份表的数据分布在不同的Map中外,其他连接的表的数据必须在每个Map中有完整的拷贝。
2.3 MapJoin适用的场景:
通过上面分析你会发现,并不是所有的场景都适合用MapJoin。它通常会用在如下的一些情景:在二个要连接的表中,有一个很大,有一个很小,这个小表可以存放在内存中而不影响性能。这样我们就把小表文件复制到每一个Map任务的本地,再让Map把文件读取内存中待用。
2.4 MapJoin的实现方法:
1)在Map-Reduce的驱动程序中使用静态方法,DistributedCache.addCacheFile() 增加要拷贝的小表文件。JobTracker在作业启动之前会获取这个URI列表,并将相应的文件拷贝到各个TaskTracker的本地磁盘上。
2)在Map类的setup方法中使用DistributedCache.getLocalCacheFiles() 方法获取文件目录,并使用标准的文件读写API读取相应的文件。
2.5 Hive 内置提供的优化机制之一就包括MapJoin
A、在Hive v0.7之前,需要使用hint 提示 才会执行MapJoin。
B、Hive v0.7之后的版本已经不需要给出MapJoin的指示就进行优化。它是通过如下配置参数来控制的:
hive> set hive.auto.convert.join=true;
Hive 还提供另外一个参数,就是:表文件的大小作为开启和关闭MapJoin的阈值。
hive> set hive.mapjoin.smalltable.filesize=25000000 即25M
文章最后,给大家推荐一些受欢迎的技术博客链接:
- JAVA相关的深度技术博客链接
- Flink 相关技术博客链接
- Spark 核心技术链接
- 设计模式 —— 深度技术博客链接
- 机器学习 —— 深度技术博客链接
- Hadoop相关技术博客链接
- 超全干货--Flink思维导图,花了3周左右编写、校对
- 深入JAVA 的JVM核心原理解决线上各种故障【附案例】
- 请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”
- 聊聊RPC通信,经常被问到的一道面试题。源码+笔记,包懂
- 深入聊聊Java 垃圾回收机制【附原理图及调优方法】
欢迎扫描下方的二维码或 搜索 公众号“大数据高级架构师”,我们会有更多、且及时的资料推送给您,欢迎多多交流!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)