对于大数据刚刚接触或想接触的朋友,希望这篇入门篇可以给到大家一些帮助,在入门的时候可以更加轻松,话不多说,请看正文。
1、RDD Dataset 和 DataFrame 速览
RDD 和 DataFrame 都是一个可以看成有很多行,每一行有若干列的数据集(姑且先按照记录和字段的概念来理解)
在 scala 中可以这样表示一个 RDD:
RDD[Array[String]] 每条记录是字符串构成的数组
RDD[(String, Int, ….)] 每条记录是多个不同类型的数据构成的元组
RDD 是分布式的 Java 对象的集合,RDD 中每个字段的数据都是强类型的
推荐一个大数据学习群 119599574晚上20:10都有一节【免费的】大数据直播课程,专注大数据分析方法,大数据编程,大数据仓库,大数据案例,人工智能,数据挖掘都是纯干货分享,你愿意来学习吗?
当在程序中处理数据的时候,遍历每条记录,每个值,往往通过索引读取
val filterRdd = rdd.filter( x => { var result = true
这种方式在 MapReduce 程序中也常常见到。
DataFrame 则是一个每列有命名的数据集,类似于关系数据库中的表,读取某一列数据的时候可以通过列名读取。所以相对于 RDD,DataFrame 提供了更详细的数据的结构信息 schema。
在 Spark 2.1 中, DataFrame 的概念已经弱化了,将它视为 DataSet 的一种实现
DataFrame is simply a type alias of Dataset[Row]
@DataFrame=org.apache.spark.sql.Dataset[org.apache.spark.sql.Row"">http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.sql.package@DataFrame=org.apache.spark.sql.Dataset[org.apache.spark.sql.Row]
除了 Row 这种类型之外,还可以是一些其他自定义的类。
Dataset API 属于用于处理结构化数据的 Spark SQL 模块(这个模块还有 SQL API),通过比 RDD 多的数据的结构信息(Schema),Spark SQL 在计算的时候可以进行额外的优化。 Spark SQL's optimized execution engine[1]。通过列名,在处理数据的时候就可以通过列名操作。
RDD、DataFrame 和 DataSet 的区别中介绍了 DatasetAPI 的优势,MLlib 里也加大了对 DataSetAPI 的支持,并且提到 The RDD-based API is expected to be removed in Spark 3.0。所以未来推荐使用 DataSetAPI。
2、使用介绍
2.1 加载数据
目前 tdw 提供了读取 tdw 表生成 RDD 或 DataFrame 的 API。
1.6API
或者直接读取 HDFS
val hdfsURL="hdfs://**/**/**/**/ds=20170101/*gz"
2.2 转换操作
1、选择指定列
//查看表的 Schema
2、map filter
val filterData = tdwDataFrame.filter( element => { var retFlag = true
这里 有两个地方需要说明 isNullAt 首先要判断要选取的列的值是否为空, 如果是空,直接读取数据会抛异常。getAs 本来是要指定具体的类型的,如 getAs[String],但因为 tdwDataFrame 的 schema 已知,包括各个字段的类型,如 gid 是 long, 这样如果按 getAs[String] 有可能会发生类型转换异常。
转换加工某些字段,即将原来的 DataFrame map 操作转换成另外一个 DataFrame。最开始的想法是用 scala 的 一些列表类型封装数据,当每个列的类型相同的时候,用数组 如 Array[String],但一般情况下是不同的,就用元组("a", 1, …),但这个方法有个局限,我们以 RDD 的操作为例,但在 DataFrame 中也是一样的
val mRdd2 = filterRdd.map(
不使用 数组和元组,而使用 Row
implicit val rowEncoder = Encoders.kryo[Row]
3、聚合分组统计
//指定列,分组统计
4、union
val unionDataFrame = aggDagaset1.union(aggDagaset2)//处理空值,将空值替换为 0.0unionData.na.fill(0.0)
5、NaN 数据中存在数据丢失
NaN,如果数据中存在 NaN(不是 null ),那么一些统计函数算出来的数据就会变成 NaN,如 avg。所以要对数据进行过滤或者转换。
import java.lang.Double.isNaNif (isNaN(x.getAs("field"))){ 0}
6、Sql 语句里一些不支持的函数或写法
不支持的函数:
url_decode
不支持的写法
not rlike
支持 rlike,所以在写正则的时候可以取反
如 not rlike '^\d $'
要求不能数字开头,数字结尾,全是数字
就可以写成 rlike '\d[*^0-9] \d[*^0-9]*'
里面至少有一个不是数字的字符
2.3 TDW 一些基础功能
val tdwUtil = new TDWUtil(Constant.tdwUser, Constant.tdwPasswd, "db")//表是否存在tdwUtil.tableExist(table)//分区是否存在tdwUtil.partitionExist(table, x)
2.4 本地测试 JUnit Test
由于 Spark 程序,需要由客户端提交给集群执行,但在程序调试阶段,想快速验证代码逻辑,通过每次提交集群执行程序太费力了,可以在本地测试一下。但其实没必要用 JUnit,但有工具何乐而不用。
import org.junit.Before
2.5 Spark environment 参数
DataFrame shuffle size 设置值
sparkSession.conf.set("spark.sql.shuffle.partitions", "200")
DataFrame groupBy cube 统计的时候,需要 shuffle,目前 tdw 的 shuffle 默认 partiton 的个数是 200, 如果数据量过大,或者 cube 的时候数据膨胀,就要适时调大这个参数。因为一个 partition 对应一个任务,增加 partition 个数,会增加并行的任务数,提高运行效率。
set("spark.default.parallelism", "10")
这个参数好有同样的效果,不过好像应用的场景是 RDD 的 reduce 操作。
2.6 写 mysql
val url = "jdbc:mysql://host:port/database?useUnicode=yes&characterEncoding=UTF-8"val connectionProperties = new Properties()
Scala JDBC 连接 Mysql,操作 mysql
Class.forName("com.mysql.jdbc.Driver")
发送 http 请求
import org.json4simport org.json4s.jackson.JsonMethods._
一篇文章看不够?不够学习?想了解更多优质文章,想要更多有关大数据方面的资料和咨询?那么你的机会来了,动手添加图片下方群号,老师带你轻松玩转大数据。其实你离掌握技能只差一条有效的学习途径。
119599574