Hive下的数据倾斜的场景
在我们的学习,还是生活中,经常会出现数据倾斜的问题,那么什么是数据倾斜问题呢,让我们来复现一下我们的要求。
首先,我写了两个表,其中user表5000万数据量,观影表2亿条数据,现如今需要的是,各个年龄段的观影数量排名。
环境:
- hadoop 2.7
- hive 1.2.1
- centos 6.8 虚拟机 1核 8G
来吧让我们愉快的去创造数据把
import java.io.{File, PrintWriter}
import java.util.UUID
import scala.util.Random
/**
* Copyright (c) 2019 wu ALL Rights Reserved
*
* Project: ScalaLanguage
* Package:
* Version: 1.0
* Created by HeartisTiger on 2019/9/8 21:19
*/
object Test01 {
def main(args: Array[String]): Unit = {
val ran = new Random()
val ages = Array[Int](15,13,25,26,27,28,29,30,32,34,38,39,40,41,58,52,61,70,80)
var age = 0;
val print1 = new PrintWriter(new File("user.txt"))
val print2 = new PrintWriter(new File("movies.txt"))
var name = ""
for(uid <- 1 to 50000000){
age = ages(ran.nextInt(ages.length))
name = UUID.randomUUID().toString
print1.println(s"$uid,$name,$age")
}
for(uid <- 1 to 200000000){
val uid = ran.nextInt(50000000)
val url = UUID.randomUUID().toString
print2.println(s"$uid,$url")
}
print1.close()
print2.close()
}
}
此时我们可以想到,看电影的年龄段,什么时候的看电影最多呢,肯定是我们的20-30-40岁依次递进的,其他的看电影的并不没有以上的年龄段的观影次数多。当然生产环境中年龄肯定不是数字表示,是用生日表示的,为了方便起见我们用年龄来制作我们的模拟数据。
这里是截取的我们的数据,我们想要求出来这个需求,我们首先应该是建立我们的测试数据表。
创建表
create table user(
id int,
name string,
age string
)
row format delimited fields terminated by ','
stored as textfile;
create table movies(
id int,
url string)
row format delimited fields terminated by ','
stored as textfile;
此时我们需要对我们的需求进行求取的过程中,需要用到mapjoin操作,此时我们可以把我们user表放置在join字段的左侧,movies放置在我们的右侧,在新版的测试当中,我们mapjoin是自动打开的,此时会在构建语法树的过程中,自动进行我们的map join 优化,所以我只是测试 放置在左边的效果。
查询语句
select age,count(1) ct from (select split(age,'')[0] * 10 as age
from user1 u join movies m on u.id = m.id)t
group by age;
此时执行了934秒的时候,我们的mapper还没有执行完毕,数据量确实比较大,我再继续耐心等待,哈哈。
先去洗澡,跑完不知道什么时候呢,我们慢慢的对我们的hive程序进行优化。
此时我们的时间消耗是34分钟,我们是否可以让我们运行时间进行进一步的缩减了。
那么我们数据倾斜发生在哪里呢,我们的数据倾斜,是发生在我们的shuffle算子的过程中,大量的key聚集到某一个reducer上进行聚合,并不是一个并行的操作,此时我们的处理时长就存在了木桶效应,也就是处理时间最长的分区决定了我们的运行的总时长。
此时我们同时尝试一下我们的spark的效果
Spark 比我们的hadoop 快了很多,其实绝大部分情况下spark比hadoop快,但是有一些很极端的情况下不一定有我们的hadoop快,这是不一定的。
我们在测试的过程中可以明显的看到,spark确实比MR快了10倍,但是这个效果,我们还是不满意怎么办呢。
DAG图
此时出现了数据倾斜问题,那么我们如何做呢
- 首先,开启map段语句和操作
set hive.map.aggr = true
- 开启在map端进行聚合的条数,这个不是随机设置的,要根据数据来计算
set hive.groupby.mapaggr.checkinterval = 10000
- 开启数据倾斜时,自动负载均衡
set hive.groupby.skewindata = true
碍于机器的性能原因,差不多也就这样了。大规模集群会很快的。