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. ...
随机推荐
- dede后台目录暴力猜解仅限于windows
#!/usr/bin/env python '''/* * author = Mochazz * team = 红日安全团队 * env = pyton3 * */ ''' import reques ...
- JS 进阶知识点及常考面试题
将会学习到一些原理相关的知识,不会解释涉及到的知识点的作用及用法,如果大家对于这些内容还不怎么熟悉,推荐先去学习相关的知识点内容再来学习原理知识. 手写 call.apply 及 bind 函数 涉及 ...
- python 第三方扩展库的安装
主要就是采用 easy_install 和pip安装,一定要把这两个东西安装好.http://peak.telecommunity.com/DevCenter/EasyInstall下载ez_setu ...
- web开发中xml的内容
文档声明(注:文档声明前不能有注释) XML中的元素/标签 注:xmlx中解析程序会将其中的空格与换行当做内容来解析,区分大小写 CDATA区域中的内容不解析
- Python学习之旅(二十五)
Python基础知识(24):正则表达式 正则表达式:检查一个字符串是否与某个模式匹配 \d :匹配数字 \w :匹配字母或数字 . :匹配任意字符 {n} :匹配n个字符 {m,n} :匹配m到n个 ...
- 使用 jQuery 调用 ASP.NET AJAX Page Method
文章来源:http://chungle.iteye.com/blog/406054 说到轻量级的客户端通信,我注意到大多数人喜欢使用 ASP.NET AJAX Page Method 多于 ASMX ...
- 限时免费 | 12月6日,广州保利洲际酒店,ABC Summit 2018云智峰会来了!
随着科技的迅猛发展,人工智能技术也逐渐取得了各个突破.自20世纪70年代以来,作为计算机学科的一个分支,人工智能就被列为世界三大尖端技术之一.近年来,阿尔法狗战胜世界第一柯洁,使人工智能再度迎来新的热 ...
- jquery网页倒计时效果,秒杀
function FreshTime(){ var endtime=new Date('2019-4-12 18:00:00');//结束时间 var nowtime = new Date();//当 ...
- 万能poi导入功能模板
同时支持2007版本和2003版本,空行过滤,纯数字类型数据格式处理,日期格式处理等 package com.yss.db.util; import com.yss.base.common.excep ...
- bootstrap 下拉菜单自动向上向下弹起
.别人的解决方案 2.别人的解决方案 3.我哒 div class="btn-group" style="margin-top:500px;" > < ...