经常看到一些Hive优化的建议中说当小表与大表做关联时,把小表写在前面,这样可以使Hive的关联速度更快,提到的原因都是说因为小表可以先放到内存中,然后大表的每条记录再去内存中检测,最终完成关联查询。这样的原因看似合理,但是仔细推敲,又站不住脚跟。 
       多小的表算小表?如果所谓的小表在内存中放不下怎么办?我用2个只有几条记录的表做关联查询,这应该算是小表了,在查看reduce的执行日志时依然是有写磁盘的操作的。实际上reduce在接收全部map的输出后一定会有一个排序所有键值对并合并写入磁盘文件的操作。写入磁盘(spill)有可能是多次的,因此有可能会生成多个临时文件,但是最终都要合并成一个文件,即最终每一个reduce都只处理一个文件。 
       我做了一个实验,用1条记录的表和3亿多条记录的表做join,无论小表是放在join的前面还是join的后面,执行的时间几乎都是相同的。再去看reduce的执行日志,1条记录的表在join前或者join后两次查询的reduce日志几乎也是一摸一样的。如果按照上面的说法把join左侧的表放内存等待join右侧的表到内存中去检测,那么当3亿多条记录的表放在join左侧时,内存肯定是无法容下这么多记录的,势必要进行写磁盘的操作,那它的执行时间应该会比小表在join前时长很多才对,但事实并不是这样,也就说明了上面说到的原因并不合理。 
       事实上“把小表放在前面做关联可以提高效率”这种说法是错误的。正确的说法应该是“把重复关联键少的表放在join前面做关联可以提高join的效率。” 
       分析一下Hive对于两表关联在底层是如何实现的。因为不论多复杂的Hive查询,最终都要转化成mapreduce的JOB去执行,因此Hive对于关联的实现应该和mapreduce对于关联的实现类似。而mapreduce对于关联的实现,简单来说,是把关联键和标记是在join左边还是右边的标识位作为组合键(key),把一条记录以及标记是在join左边还是右边的标识位组合起来作为值(value)。在reduce的shuffle阶段,按照组合键的关联键进行主排序,当关联键相同时,再按照标识位进行辅助排序。而在分区段时,只用关联键中的关联键进行分区段,这样关联键相同的记录就会放在同一个value list中,同时保证了join左边的表的记录在value list的前面,而join右边的表的记录在value list的后面。 
       例如A join B ON (A.id = b.id) ,假设A表和B表都有1条id = 3的记录,那么A表这条记录的组合键是(3,0),B表这条记录的组合键是(3,1)。排序时可以保证A表的记录在B表的记录的前面。而在reduce做处理时,把id=3的放在同一个value list中,形成 key = 3,value list = [A表id=3的记录,B表id=3的记录] 
       接下来我们再来看当两个表做关联时reduce做了什么。Reduce会一起处理id相同的所有记录。我们把value list用数组来表示。 
       1)   Reduce先读取第一条记录v[0],如果发现v[0]是B表的记录,那说明没有A表的记录,最终不会关联输出,因此不用再继续处理这个id了,读取v[0]用了1次读取操作。 
       2)   如果发现v[0]到v[length-1]全部是A表的记录,那说明没有B表的记录,同样最终不会关联输出,但是这里注意,已经对value做了length次的读取操作。 
       3)   例如A表id=3有1条记录,B表id=3有10条记录。首先读取v[0]发现是A表的记录,用了1次读取操作。然后再读取v[1]发现是B表的操作,这时v[0]和v[1]可以直接关联输出了,累计用了2次操作。这时候reduce已经知道从v[1]开始后面都是B 表的记录了,因此可以直接用v[0]依次和v[2],v[3]……v[10]做关联操作并输出,累计用了11次操作。 
       4)   换过来,假设A表id=3有10条记录,B表id=3有1条记录。首先读取v[0]发现是A表的记录,用了1次读取操作。然后再读取v[1]发现依然是A表的记录,累计用了2次读取操作。以此类推,读取v[9]时发现还是A表的记录,累计用了10次读取操作。然后读取最后1条记录v[10]发现是B表的记录,可以将v[0]和v[10]进行关联输出,累计用了11次操作。接下来可以直接把v[1]~v[9]分别与v[10]进行关联输出,累计用了20次操作。 
       5)   再复杂一点,假设A表id=3有2条记录,B表id=3有5条记录。首先读取v[0]发现是A表的记录,用了1次读取操作。然后再读取v[1]发现依然是A表的记录,累计用了2次读取操作。然后读取v[2]发现是B表的记录,此时v[0]和v[2]可以直接关联输出,累计用了3次操作。接下来v[0]可以依次和v[3]~v[6]进行关联输出,累计用了7次操作。接下来v[1]再依次和v[2]~v[6]进行关联输出,累计用了12次操作。 
       6)   把5的例子调过来,假设A表id=3有5条记录,B表id=3有2条记录。先读取v[0]发现是A表的记录,用了1次读取操作。然后再读取v[1]发现依然是A表的记录,累计用了2次读取操作。以此类推,读取到v[4]发现依然是A表的记录,累计用了5次读取操作。接下来读取v[5],发现是B表的记录,此时v[0]和v[5]可以直接关联输出,累计用了6次操作。然后v[0]和v[6]进行关联输出,累计用了7次操作。然后v[1]分别与v[5]、v[6]关联输出,累计用了9次操作。V[2] 分别与v[5]、v[6]关联输出,累计用了11次操作。以此类推,最后v[4] 分别与v[5]、v[6]关联输出,累计用了15次操作。 
       7)   额外提一下,当reduce检测A表的记录时,还要记录A表同一个key的记录的条数,当发现同一个key的记录个数超过hive.skewjoin.key的值(默认为1000000)时,会在reduce的日志中打印出该key,并标记为倾斜的关联键。 
       最终得出的结论是:写在关联左侧的表每有1条重复的关联键时底层就会多1次运算处理。 
       假设A表有一千万个id,平均每个id有3条重复值,那么把A表放在前面做关联就会多做三千万次的运算处理,这时候谁写在前谁写在后就看出性能的差别来了。

Hive中小表与大表关联(join)的性能分析相关推荐

  1. 【hive】数据倾斜-大表小表join优化mapjoin

    真正让你明白Hive调优系列3:笛卡尔乘积,小表join大表,Mapjoin等问题 0.Hive中的优化分类    真正想要掌握Hive的优化,要熟悉相关的MapReduce,Yarn,hdfs底层源 ...

  2. Hive SQL 小表与大表Join 原理与实操

    一.案例演示 1)没有使用map join -- a 表是大表,数据量是百万级别 -- b 表是小表,数据量在百级别 select a.field1 as field1,b.field2 as fie ...

  3. MySQL IN、Exist关联查询时,我们为什么建议小表驱动大表?

    有的时候我们在操作数据库时会将两个或多个数据表关联起来通过一些条件筛选数据,在关联表时我们要遵循一些原则,这样会使我们编写的SQL 语句在效率上快很多. 一.优化原则 小表驱动大表,即小的数据集驱动大 ...

  4. MySQL关联查询时,我们为什么建议小表驱动大表?

    作者:留兰香丶 blog.csdn.net/codejas/article/details/78632883 有的时候我们在操作数据库时会将两个或多个数据表关联起来通过一些条件筛选数据,在关联表时我们 ...

  5. mysql 小表连大表_MySQL 表之间关联查询时,为什么建议小表驱动大表?

    有的时候我们在操作数据库时会将两个或多个数据表关联起来通过一些条件筛选数据,在关联表时我们要遵循一些原则,这样会使我们编写的SQL 语句在效率上快很多. 一.优化原则 小表驱动大表,即小的数据集驱动大 ...

  6. oracle 表连接 大表小表_优化必备基础:Oracle中常见的三种表连接方式

    在Oracle SQL语句中,如果from后面有多个表时,表的连接方式是一个很重要的考量. 从Oracle 6开始,优化器就支持下面4种表连接方式: - 嵌套循环连接(Nested Loop Join ...

  7. NL连接一定是小表驱动大表效率高吗

    前言 两表使用nest loop(以下简称NL)方式进行连接,小表驱动大表效率高,这似乎是大家的共识,但事实上这是有条件的,并不总是成立.这主要看大表扫描关联字段索引后返回多少数据量,是否需要回表,如 ...

  8. Mysql优化原则_小表驱动大表IN和EXISTS的合理利用

    //假设一个for循环 for($i = 0; $i < 10000; $i++) { for ($j = 0; $i < 50; $j++){} }for($i = 0; $i < ...

  9. MySql小表驱动大表

    有的时候我们在操作数据库时会将两个或多个数据表关联起来通过一些条件筛选数据,在关联表时我们要遵循一些原则,这样会使我们编写的SQL 语句在效率上快很多. 一.优化原则 小表驱动大表,即小的数据集驱动大 ...

最新文章

  1. 2022-2028年中国PET基膜行业市场发展规模及市场分析预测报告
  2. Keil调试局部变量显示not in scope的问题解决
  3. android 打开免打扰模式_三星S10+免root也能完美使用Xp框架?这款神器你必须要知道...
  4. Python学习笔记:文件读/写方法汇总
  5. java集合框架(set)
  6. 莫代尔是什么?它有哪些优缺点?
  7. 使用 Gogs 搭建自己的 Git 服务器
  8. 皮尔逊相关系数和斯皮尔曼相关系数(等级系数)与典型相关分析
  9. 群联PS2251-07主控(Kingston64G)量产CD-ROM+移动磁盘模式过程记录
  10. 面向对象的英文全称叫做Object Oriented
  11. kali制作钓鱼网站
  12. 控制面板中点击管理工具提示administrative tools 位置不可用的解决办法
  13. 基于微服务的个人博客系统
  14. 射频识别技术:RFID 您了解不?
  15. 你有多久没有收到圣诞节的祝福了,你收到那个女孩(男孩)的祝福了吗?
  16. Springboot整合Shiro之授权
  17. antd 表格加y轴滚动时行与行间错位问题
  18. VS Code 国内官网快速下载
  19. Python + Django4 搭建个人博客(十):实现文章详情页面
  20. 浏览器的审查元素,这是一个神奇的玩意儿

热门文章

  1. JavaScript 伪数组和数组
  2. JD青龙面板任务代理池部署与使用教程
  3. 预装Win10的电脑改Win7的方法
  4. 解读本世纪最成功的天才——埃隆·马斯克
  5. 【论文笔记】DOA-GAN: Dual-Order Attentive Generative Adversarial Network for Image Copy-move Forgery Detec
  6. OpenSSL简单使用
  7. 前端鼠标触碰实现遮罩方法
  8. 解决iPhone部分机型下面有小黑条遮挡问题
  9. 当前使用的windows版本不支持该处理器,系统将错失重要的安全更新怎么办
  10. 部队计算机考试题,军队文职面试计算机题库_江苏军队人才网