dataFrame、dataSet整理
1.RDD是什么?
RDD:弹性分布式数据集,就是数据的一个不可变的分布式元素集合,在集群中跨节点分布。可以把他的内部元素看成是一个Java对象。
2.DataFrame是什么?
DataFrame:以RDD为基础的分布式数据集,与RDD不同点在于DataFrame中的数据都被组织到有名称的列中,类似于一个表结构。可以把他内部元素看成是一个Row对象。
在一个 SparkSession中,应用程序可以从一个 已经存在的 RDD,从hive表,或者从 Spark数据源中创建一个DataFrames。
3.创建一个DataFrame
创建Dataframe可以通过三种方式:1、从现有的RDD转换 2、从Hive Table转换 3、从spark支持的DataSource转换
1、从现有RDD使用类的反射机制
// Create an RDD of Person objects from a text file
JavaRDD<Person> peopleRDD = spark.read()
.textFile("examples/src/main/resources/people.txt")
.javaRDD()
.map(line -> {
String[] parts = line.split(",");
Person person = new Person();
person.setName(parts[0]);
person.setAge(Integer.parseInt(parts[1].trim()));
return person;
});
// Apply a schema to an RDD of JavaBeans to get a DataFrame
Dataset<Row> peopleDF = spark.createDataFrame(peopleRDD, Person.class);
2、从现有RDD自定义schema
// Create an RDD
JavaRDD<String> peopleRDD = spark.sparkContext()
.textFile("examples/src/main/resources/people.txt", 1)
.toJavaRDD();
// The schema is encoded in a string
String schemaString = "name age";
// Generate the schema based on the string of schema
List<StructField> fields = new ArrayList<>();
for (String fieldName : schemaString.split(" ")) {
StructField field = DataTypes.createStructField(fieldName, DataTypes.StringType, true);
fields.add(field);
}
StructType schema = DataTypes.createStructType(fields);
// Convert records of the RDD (people) to Rows
JavaRDD<Row> rowRDD = peopleRDD.map((Function<String, Row>) record -> {
String[] attributes = record.split(",");
return RowFactory.create(attributes[0], attributes[1].trim());
});
// Apply the schema to the RDD
Dataset<Row> peopleDataFrame = spark.createDataFrame(rowRDD, schema);
3.从spark数据源中获取
Dataset<Row> df = spark.read().json("examples/src/main/resources/people.json");
4.DataFrame和RDD的优缺点
1、RDD的优点:
- 编译时类型安全
- 具有面向对象的风格
缺点:
- 构建大量Java对象,占用大量堆内存,导致频繁GC影响效率
- 序列化反序列化性能开销大
2、DataFrame的优点:
- 引入了off-heap(堆外),这样在构建对象时就会使用操作系统层面的内存,不会占用堆内存,避免了频繁GC
- 引入了schema元数据,在大量数据传输时只需要序列化和反序列化数据本身而不需要传输结构信息,减少了性能开销。
缺点:
- 编译时类型不安全,只有在运行时才能发现错误
- 不再具有面向对象的编程风格
5.DataSet是什么?
DataSet是分布式的数据集合,Dataset提供了强类型支持,也是在RDD的每行数据加了类型约束。
6.创建一个DataSet
1、使用JavaBean类型创建
Person person = new Person();
person.setName("Andy");
person.setAge(32);
// Encoders are created for Java beans
Encoder<Person> personEncoder = Encoders.bean(Person.class);
Dataset<Person> javaBeanDS = spark.createDataset(
Collections.singletonList(person),
personEncoder
);
2、使用list创建
// Encoders for most common types are provided in class Encoders
Encoder<Integer> integerEncoder = Encoders.INT();
Dataset<Integer> primitiveDS = spark.createDataset(Arrays.asList(1, 2, 3), integerEncoder);
Dataset<Integer> transformedDS = primitiveDS.map(
(MapFunction<Integer, Integer>) value -> value + 1,
integerEncoder);
3、通过读取文件创建DataFrame,再转换为DataSet
// DataFrames can be converted to a Dataset by providing a class. Mapping based on name
String path = "examples/src/main/resources/people.json";
Dataset<Person> peopleDS = spark.read().json(path).as(personEncoder);
7.RDD、DataSet、DataFrame之间的区别
1、RDD与DataFrame之间的区别
- 提升执行效率:heap-off避免了频繁GC、引入了schema,减少了序列化的性能开销
- 减少数据读取:dataframe可以通过sql语句筛选掉不想要的行或者列
- 执行优化:filter下推,先join再filter->先filter再join
2、RDD与DataSet之间的区别
- DataSet以Catalyst逻辑执行计划表示,并且数据以编码的二进制形式被存储,不需要反序列化就可以执行sorting、shuffle等操作。
- DataSet创立需要一个显式的Encoder,把对象序列化为二进制,可以把对象的scheme映射为Spark SQl类型,然而RDD依赖于运行时反射机制。
3、DataSet和DataFrame之间的区别
- DataSet可以在编译时检查类型
- DataSet是面向对象的编程接口
- DataFrame和DataSet可以相互转化,df.as[ElementType]这样可以把DataFrame转化为DataSet,ds.toDF()这样可以把DataSet转化为DataFrame。