spark生成大宽表的parquet性能优化
1. 背景介绍
2. 第一版实现过程
private def CTRL_A = '\001'
private def CTRL_B = '\002'
private def CTRL_C = '\003'
def main(args: Array[String]): Unit = {
val resourcePath = this.getClass.getResource("/resource.txt").getFile
val sourcePath = this.getClass.getResource("/*.gz").getFile
val output = "/home/dev/output"
val conf = new SparkConf().setAppName("user test").setMaster("local")
val sc = new SparkContext(conf)
val sqlContext = new SQLContext(sc)
sqlContext.setConf("spark.sql.parquet.binaryAsString", "true")
sqlContext.setConf("spark.sql.inMemoryColumnarStorage.compressed", "true")
sqlContext.setConf("spark.sql.parquet.compression.codec", "snappy")
val map: Map[String, String] = buildResource(resourcePath)
val schema = buildSchema(map)
val bd = sc.broadcast(map)
val bdSchema = sc.broadcast(schema)
val start=System.currentTimeMillis()
val rdd = sc.textFile(sourcePath)
.map(line => {
val map = buildUser(line, bd.value)
buildRow(map._3, map._1, map._2)
})
// rdd.foreach(_=>())
// sqlContext.createDataFrame(rdd, bdSchema.value).write.mode(SaveMode.Overwrite).json(output)
sqlContext.createDataFrame(rdd, bdSchema.value).write.mode(SaveMode.Overwrite).parquet(output)
val end = System.currentTimeMillis()
System.out.print(end - start)
}
/**
* 读取资源文件
* @param file
* @return
*/
def buildResource(file: String): Map[String, String] = {
val reader = Source.fromFile(file)
val map = new mutable.HashMap[String, String]()
for (line <- reader.getLines() if !Strings.isNullOrEmpty(line)) {
val arr = StringUtils.splitPreserveAllTokens(line, '\t')
map.+=((arr(0), "0"))
}
map.toMap
}
/**
* 生成用户属性
* @param line
* @param map
* @return
*/
def buildUser(line: String, map: Map[String, String]): (String, Int, Map[String, String]) = {
if (Strings.isNullOrEmpty(line)) {
return ("", 0, Map.empty)
}
val array = StringUtils.splitPreserveAllTokens(line, CTRL_A)
val cookie = if (Strings.isNullOrEmpty(array(0))) "-" else array(0)
val platform = array(1).toInt
val base = buildFeature(array(2))
val interest = buildFeature(array(3))
val buy = buildFeature(array(4))
val features = base ++ interest ++ buy
val result = new mutable.HashMap[String, String]()
for (pair <- map) {
val value = if (features.contains(pair._1)) "1" else "0"
result.+=((pair._1, value))
}
(cookie, platform, result.toMap)
}
/**
* 抽取用户标签
* @param expr
* @return
*/
def buildFeature(expr: String): Array[String] = {
if (Strings.isNullOrEmpty(expr)) {
return Array.empty
}
val arr = StringUtils.splitPreserveAllTokens(expr, CTRL_B)
val buffer = new ArrayBuffer[String]()
for (key <- arr) {
val pair = StringUtils.splitPreserveAllTokens(key, CTRL_C)
buffer += (s"_${pair(0)}")
}
buffer.toArray
}
/**
* 动态生成DataFrame的Schema
* @param map
* @return
*/
def buildSchema(map: Map[String, String]): StructType = {
val buffer = new ArrayBuffer[StructField]()
buffer += (StructField("user", StringType, false))
buffer += (StructField("platform", IntegerType, false))
for (pair <- map) {
buffer += (StructField(s"_${pair._1}", IntegerType, true))
}
return StructType(List(buffer: _*))
}
/**
* 将用户属性构造成Spark SQL的Row
* @param map
* @param user
* @param platform
* @return
*/
def buildRow(map: Map[String, String], user: String, platform: Int): Row = {
val buffer = new ArrayBuffer[Any]()
buffer += (user)
buffer += (platform)
for (pair <- map) {
buffer += (pair._2.toInt)
}
return Row(buffer: _*)
}
3. 第二版实现过程
在第一版中初步怀疑是DataFrame在生成parquet时进行了一些特殊逻辑的处理,所以决定自己实现ParquetWriter方法来测试下性能,采用了avro来向parquet中写入数据。方法大概包含定义好avro资源文件,然后使用AvroParquetWriter类来向parquet中写入内容,具体的写入方法类似于https://blog.csdn.net/gg584741/article/details/51614752。通过这种方式来写入parquet,相同数据量的情况下,性能提升了一倍多。至于为什么性能有这么大的提升,有待后续研究。到此优化就告一段落了。
val Schema = (new Schema.Parser()).parse(new File(file))
来动态生成Schema来供后续AvroParquetWriter使用。
spark生成大宽表的parquet性能优化的更多相关文章
- Spark Tungsten揭秘 Day1 jvm下的性能优化
Spark Tungsten揭秘 Day1 jvm下的性能优化 今天开始谈下Tungsten,首先我们需要了解下其背后是符合了什么样的规律. jvm对分布式天生支持 整个Spark分布式系统是建立在分 ...
- Hadoop如何将TB级大文件的上传性能优化上百倍?
这篇文章,我们来看看,Hadoop的HDFS分布式文件系统的文件上传的性能优化. 首先,我们还是通过一张图来回顾一下文件上传的大概的原理. 由上图所示,文件上传的原理,其实说出来也简单. 比如有个TB ...
- android app性能优化大汇总(UI渲染性能优化)
UI性能测试 性能优化都需要有一个目标,UI的性能优化也是一样.你可能会觉得“我的app加载很快”很重要,但我们还需要了解终端用户的期望,是否可以去量化这些期望呢?我们可以从人机交互心理学的角度来考虑 ...
- 一次EF批量插入多表数据的性能优化经历
距离上次的博客已经有15个多月了,感慨有些事情还是需要坚持,一旦停下来很有可能就会停很久或者从此再也不会坚持.但我个人一直还坚持认为属于技术狂热份子,且喜欢精益求精的那种.最近遇到两个和数据迁移相关的 ...
- kettle大数据量读写mysql性能优化
修改kettleDB连接设置 1. 增加批量写的速度:useServerPrepStmts=false rewriteBatchedStatements=true useCompressio ...
- Sql Server RowNumber和表变量分页性能优化小计
直接让代码了,对比看看就了解了 当然,这种情况比较适合提取字段较多的情况,要酌情而定 性能较差的: WITH #temp AS ( ...
- android app性能优化大汇总
这里根据网络上各位大神已经总结的知识内容做一个大汇总,作为记录,方便后续“温故知新”. 性能指标: (1)使用流畅度: 图片处理器每秒刷新的帧数(FPS),可用来指示页面是否平滑的渲染.高的帧率可以 ...
- Oracle12c 性能优化攻略:攻略1-3: 匹配表类型与业务需求
注:目录表 <Oracle12c 性能优化攻略:攻略目录表> 问题描述 你刚开始使用oracle数据库,并且学习了一些关于可用的各种表类型的知识.例如:可以在堆组织表.索引组织表等之间支出 ...
- Elasticsearch 通关教程(七): Elasticsearch 的性能优化
硬件选择 Elasticsearch(后文简称 ES)的基础是 Lucene,所有的索引和文档数据是存储在本地的磁盘中,具体的路径可在 ES 的配置文件../config/elasticsearch. ...
随机推荐
- mybatis14--注解的配置
去掉对应的mapper映射文件 在dao文件中增加注解 public interface StudentDao { /** * 新增学生信息 */ @Insert(value="insert ...
- ora-01017 和oracle database link
DB link ,创建完了后总是报密码错误.我感到奇怪.明明密码是对的.怎么可能错误呢. SQL> create public database link kk40 connect to khf ...
- 解决vue单页路由跳转后scrollTop的问题
作为vue的初级使用者,在开发过程中遇到的坑太多了.在看页面的时候发现了页面滚动的问题,当一个页面滚动了,点击页面上的路由调到下一个页面时,跳转后的页面也是滚动的,滚动条并不是在页面的顶部 在我们写路 ...
- layer loading层 的设置
/* shadeClose 类型:Boolean 默认:true,是否点击遮罩时关闭层 */ var tishi = layer.open({ shadeClose: false ,type: 2 , ...
- String字面量
public class assa{ static String ee = "aa";//ee指向常量池中的aa static String ff = new String(&qu ...
- Ps去除背景
http://www.16xx8.com/photoshop/jiaocheng/26905.html
- BeeHive小思考
事件分发和事件处理 将所有行为注册为不同的时间类型,配置Module,让他们在事件发生时,响应这些事件(除了系统的事件,还可以注册自定义事件,触发自定义事件) Module注册之后应当会生成单例对象, ...
- 新手学习Linux之快速上手分析
一.起步 首先,应该为自己创造一个学习linux的环境--在电脑上装一个linux或unix 问题1:版本的选择 北美用redhat,欧洲用SuSE,桌面mandrake较多,而debian是技术最先 ...
- 黏包:传输过程中 read(不可靠)传输时由于网络造成黏包
但是你在读取本地文件 不涉及传输文件时 read还是可靠的
- python下载网页视频
因网站不同需要修改. 下载 mp4 连接 from bs4 import BeautifulSoup import requests import urllib import re import js ...