SparkSQL-创建Datasets

本文探讨了Spark中Dataset与RDD的主要区别,重点在于Dataset如何利用编码器进行高效序列化,以及如何在Java中创建和使用Dataset。通过实例展示了如何为JavaBean对象创建编码器,以及如何读取JSON文件并将其转换为Dataset。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Dataset 与 RDD 相似,然而并不是使用 Java 序列化或者 Kryo编译器来序列化用于处理或者通过网络进行传输的对象。虽然编码器和标准的序列化都负责将一个对象序列化成字节,编码器是动态生成的代码,并且使用了一种允许 Spark 去执行许多像 filtering,,sorting 以及 hashing 这样的操作,不需要将字节反序列化成对象的格式。

import java.util.Arrays;
import java.util.Collections;
import java.io.Serializable;

import org.apache.spark.api.java.function.MapFunction;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.Encoder;
import org.apache.spark.sql.Encoders;

public static class Person implements Serializable {
  private String name;
  private int age;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

// JavaBean对象
// Create an instance of a Bean class
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
);
javaBeanDS.show();
// +---+----+
// |age|name|
// +---+----+
// | 32|Andy|
// +---+----+

// 基本类型
// 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);
transformedDS.collect(); // Returns [2, 3, 4]

// JSON文件
// 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);
peopleDS.show();
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

 

### Spark SQL 使用指南 #### 创建 SparkSession Spark 中的所有功能都由 `SparkSession` 类作为入口点。以下是创建一个基础的 `SparkSession` 的方法: ```scala import org.apache.spark.sql.SparkSession val spark = SparkSession .builder() .appName("Spark SQL Example") .config("spark.some.config.option", "some-value") .getOrCreate() // 隐式转换支持,例如将 RDD 转换为 DataFrame import spark.implicits._ ``` 上述代码展示了如何初始化一个 `SparkSession` 实例并配置其名称和选项[^1]。 --- #### 处理 Datasets 和 DataFrames 在 Spark SQL 中,`DataFrame` 是一种分布式的数据结构,类似于关系型数据库中的表。可以通过多种方式加载数据到 DataFrame 或 Dataset 中。以下是一个简单的例子,展示如何读取 CSV 文件并执行查询: ```scala // 加载 CSV 数据 val df = spark.read.format("csv").option("header", "true").load("path/to/csv") // 显示前几行数据 df.show() // 执行简单过滤操作 val filteredDF = df.filter($"age" > 20) // 注册临时视图以便使用 SQL 查询 filteredDF.createOrReplaceTempView("people") // 运行 SQL 查询 val result = spark.sql("SELECT * FROM people WHERE age > 30") result.show() ``` 此部分演示了如何加载外部数据源、应用过滤器以及运行 SQL 查询[^2]。 --- #### 日期时间转换 在实际场景中,经常需要对日期和时间字段进行处理。Spark SQL 提供了一系列内置函数来简化这一过程。常用的函数包括但不限于以下几个: - **to_date**: 将字符串转换为日期类型。 - **to_timestamp**: 将字符串转换为时间戳类型。 - **date_format**: 格式化日期或时间戳。 - **datediff**: 计算两个日期之间的天数差。 下面是一些具体的用法示例: ```sql -- 假设有一个名为 events 的表,其中包含 timestamp 字段 SELECT to_date(timestamp, 'yyyy-MM-dd') AS date_col, to_timestamp(timestamp, 'yyyy-MM-dd HH:mm:ss') AS ts_col, date_format(to_date(timestamp), 'MM/dd/yyyy') AS formatted_date, datediff(current_date(), to_date(timestamp)) AS days_diff FROM events; ``` 这段代码说明了如何利用 Spark SQL 函数完成常见的日期时间转换任务[^3]。 --- #### 控制输出文件数量 当写入大数据集时,默认情况下可能会生成大量小型文件。为了优化性能和管理方便,可以使用合并提示(merge hints),这使得用户能够像在 Dataset API 中那样控制输出分区的数量。具体实现如下所示: ```scala // 合并分区以减少输出文件数量 val repartitionedDF = df.repartition(10) // 设置为 10 个分区 // 写入结果到 HDFS 或其他存储系统 repartitionedDF.write.mode("overwrite").parquet("output/path") ``` 这种方法有助于提高下游系统的效率,并减少了不必要的小文件开销[^4]。 --- ### 总结 以上内容涵盖了 Spark SQL 的核心概念及其典型应用场景,包括创建 `SparkSession`、处理 Datasets/DataFrames、日期时间转换以及调整输出文件大小等方面的知识点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值