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. ...
随机推荐
- html5与css 1. web标准及组成
学习目标 1.本专业介绍.HTML相关概念,HTML发展历史 2.WEB标准,W3C/WHATWG/ECMA相关概念 3.相关软件的应用以及站点的创建 4.HTML基本结构和HTML语法 5.HTML ...
- java个人博客源码
初入博客园,请各位多关照,来而不往非礼也. 如需要源码以及学习内容,qq:1397617269,我看到就回你们资源. 直接给链接: 链接:https://pan.baidu.com/s/1S_awtg ...
- input 设置 width:100% 和padding后宽度超出父节点
input 设置 width:100% 和padding后宽度超出父节点 添加如下css即可: box-sizing: border-box; -webkit-box-sizing: border-b ...
- js设计模式(六)---命令模式
命令模式算是最简单.优雅的模式之一了,命令模式中的命令指的是一个执行某些特定事情的指令.目的是吧请求发送者和请求接受者解耦, 就像点餐,顾客只需要发送菜单,谁去接收,不用考虑.厨师接收到命令开始做菜, ...
- MySQL数据库一些常用命令
输入mysql –u root(用户名) -p 回车后输入密码,就可以连接到mysql数据库. 1. 创建数据库:create database 数据库名称: 2. 删除数据库:drop databa ...
- 从javaScript中学习正则表达式——RegExp
正则表达式工具:http://regexper.com 由于国外网络可以选择 https://github.com/javallone/regexper-static 离线安装作为本地服务. 正则 ...
- Android开发网【申明:来源于网络】
Android开发网[申明:来源于网络] 地址:http://www.jizhuomi.com/android/video/
- 洛谷P3369 【模板】普通平衡树
题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(排名定义为比当前数小的数的个数+1.若有多 ...
- fiddler 修改
很多新手学习fiddler抓包的同学们都会对https网站抓包难或者抓不起来的问题无所适从,想寻求解决办法,没问题,这节课就来解决你的疑问! 最典型的网站就是目前的百度网站了,百度在近些年采用了htt ...
- ASP.NET Core 中读取 Request.Body 的正确姿势
ASP.NET Core 中的 Request.Body 虽然是一个 Stream ,但它是一个与众不同的 Stream —— 不允许 Request.Body.Position=0 ,这就意味着只能 ...