Spark SQL 之 DataFrame 创建的几种方式

SparkSQL 组件在Spark 体系中架构图

在这里插入图片描述

DataFrame
Dataframe 的概念有点像传统数据库中的表,每一条记录都代表了一个 Row Object.
与RDD的API 类似,DataFrame 的API 可以分为2种: transformations and actions.
Dataframe 可以从 Hive 或者其他的 database 中读取创建。
如何创建 DataFrame?
案例1.Create DataFrame from RDD
在项目的pom.xml 加入spark-sql的依赖包
  <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql_2.11</artifactId>
      <version>2.4.0</version>
    </dependency>
val sc = new SparkContext(conf);
val spark =  SparkSession.builder().config(conf).getOrCreate();
sc.setLogLevel("ERROR");
val strRDD = sc.parallelize(List(Row("jason",33),Row("Tom",50)));
val schema = StructType(List(
      StructField("Name",StringType,true),
      StructField("Age",IntegerType,true)
    ));
val df = spark.createDataFrame(strRDD,schema);
df.printSchema();
df.show();
输出日志
root
 |-- Name: string (nullable = true)
 |-- Age: integer (nullable = true)

+-----+---+
| Name|Age|
+-----+---+
|jason| 33|
|  Tom| 50|
+-----+---+
案例2. Creating DataFrames from a Range of Numbers
 val spark =  SparkSession.builder().config(conf).getOrCreate();
 spark.range(1,100).toDF("Num").show();
输出日志
+---+
|Num|
+---+
|  1|
|  2|
|  3|
|  4|
|  5|
|  6|
|  7|
|  8|
|  9|
| 10|
| 11|
| 12|
| 13|
| 14|
| 15|
| 16|
| 17|
| 18|
| 19|
| 20|
+---+
only showing top 20 rows
案例2. Creating DataFrames from Collection Tuple
 val spark =  SparkSession.builder().config(conf).getOrCreate();
 val person = Seq(("Jason","DBA"),("Chen","Dev"))
 val df = spark.createDataFrame(person).toDF("Name","jobs");
 df.printSchema();
 df.show();
输出日志

root
 |-- Name: string (nullable = true)
 |-- jobs: string (nullable = true)
 +-----+----+
| Name|jobs|
+-----+----+
|Jason| DBA|
| Chen| Dev|
+-----+----+
接下来的案例将演示:如何从DATASOURCE 中创建RDD
案例1. 从TXT文本中创建 RDD
val spark =  SparkSession.builder().config(conf).getOrCreate();
val df = spark.read.text("file:///c://README.txt");
df.show(300);
输出日志
+--------------------+
|               value|
+--------------------+
|      TCPDF - README|
|=================...|
|                    |
|I WISH TO IMPROVE...|
|PLEASE MAKE A DON...|

案例2. Creating DataFrames by Reading CSV Files
val spark = SparkSession.builder().config(conf).getOrCreate();
val df = spark.read.option("header",true).csv("file:///c://samle1.csv");
df.show();
输出日志
+---+-----------+----+
|   |ID_PROVINCE|NAME|
+---+-----------+----+
|  1|         91|泰安|
|  2|         91|济宁|
|  3|         91|临沂|
|  4|         77|孝感|
|  5|         77|黄冈|
|  6|         69|娄底|
|  7|         69|益阳|
|  8|         69|怀化|
|  9|         69|永州|
| 10|         69|邵阳|
| 11|         91|莱芜|
| 12|         77|鄂州|
| 13|         77|随州|
| 14|         74|安庆|
| 15|         74|蚌埠|
| 16|         74|亳州|
| 17|         74|池州|
| 18|         74|滁州|
| 19|         74|阜阳|
| 20|         74|合肥|
+---+-----------+----+
only showing top 20 rows
案例2. Creating DataFrames by Reading TSV Files
 val spark = SparkSession.builder().config(conf).getOrCreate();
    val schema = StructType(List(
      StructField("ID",IntegerType,true) ,
      StructField("PID",IntegerType,true),
      StructField("省份",StringType,true)

    ));
    val df = spark.read.option("head",true).option("sep","\t").schema(schema).csv("file:///c://sample2.tsv");
    df.show();
输出日志
+----+----+----+
|  ID| PID|省份|
+----+----+----+
|null|null|null|
|   1|  91|泰安|
|   2|  91|济宁|
|   3|  91|临沂|
|   4|  77|孝感|
|   5|  77|黄冈|
|   6|  69|娄底|
|   7|  69|益阳|
|   8|  69|怀化|
|   9|  69|永州|
|  10|  69|邵阳|
|  11|  91|莱芜|
|  12|  77|鄂州|
|  13|  77|随州|
|  14|  74|安庆|
|  15|  74|蚌埠|
|  16|  74|亳州|
|  17|  74|池州|
|  18|  74|滁州|
|  19|  74|阜阳|
+----+----+----+
only showing top 20 rows
案例3. Creating DataFrames by Reading JSON Files
 val spark = SparkSession.builder().config(conf).getOrCreate();
 val df = spark.read.json("file:///c://notification.json");
 df.printSchema();
 df.show();
输出日志
root
 |-- _class: string (nullable = true)
 |-- _id: struct (nullable = true)
 |    |-- $oid: string (nullable = true)
 |-- expireTime: struct (nullable = true)
 |    |-- $date: string (nullable = true)
 |-- insertDate: struct (nullable = true)
 |    |-- $date: string (nullable = true)
 |-- notificationId: string (nullable = true)
 |-- notificationResult: struct (nullable = true)
 |    |-- _id: string (nullable = true)
 |    |-- idApp: string (nullable = true)
 |    |-- idNotification: string (nullable = true)
 |    |-- status: string (nullable = true)
 |    |-- statusDesc: string (nullable = true)
 |-- notificationStatus: string (nullable = true)
 |-- sendTime: struct (nullable = true)
 |    |-- $numberLong: string (nullable = true)
 |-- status: string (nullable = true)
 +--------------------+--------------------+--------------------+--------------------+--------------+--------------------+------------------+---------------+------------+
|              _class|                 _id|          expireTime|          insertDate|notificationId|  notificationResult|notificationStatus|       sendTime|      status|
+--------------------+--------------------+--------------------+--------------------+--------------+--------------------+------------------+---------------+------------+
|cn.homecredit.ngw...|[5c3d50f6e4b0a0b3...|[2019-02-13T16:00...|[2019-01-15T03:18...|     245884248|[181374678, 2, 24...|                 0|[1547522294576]|Wait4Persist|
|cn.homecredit.ngw...|[5c3d50f6e4b0a0b3...|[2019-02-13T16:00...|[2019-01-15T03:18...|     245884249|[181374679, 2, 24...|                 0|[1547522294886]|Wait4Persist|
|cn.homecredit.ngw...|[5c3d7a43e4b0673d...|[2019-02-13T16:00...|[2019-01-15T06:14...|     245884250|[181374680, 2, 24...|                 0|[1547532867318]|Wait4Persist|
|cn.homecredit.ngw...|[5c3da976e4b043d0...|[2019-02-13T16:00...|[2019-01-15T09:35...|     245884251|[181374681, 2, 24...|                 0|[1547544950160]|Wait4Persist|
|cn.homecredit.ngw...|[5c3da976e4b043d0...|[2019-02-13T16:00...|[2019-01-15T09:35...|     245884253|[181374683, 2, 24...|                 0|[1547544950176]|Wait4Persist|
|cn.homecredit.ngw...|[5c3da976e4b043d0...|[2019-02-13T16:00...|[2019-01-15T09:35...|     245884254|[181374682, 2, 24...|                 0|[1547544950175]|Wait4Persist|
|cn.homecredit.ngw...|[5c3da976e4b043d0...|[2019-02-13T16:00...|[2019-01-15T09:35...|     245884255|[181374684, 2, 24...|                 0|[1547544950181]|Wait4Persist|
|cn.homecredit.ngw...|[5c3da976e4b043d0...|[2019-02-13T16:00...|[2019-01-15T09:35...|     245884263|[181374693, 2, 24...|                 0|[1547544950259]|Wait4Persist|
|cn.homecredit.ngw...|[5c3da976e4b043d0...|[2019-02-13T16:00...|[2019-01-15T09:35...|     245884265|[181374694, 2, 24...|                 0|[1547544950261]|Wait4Persist|
|cn.homecredit.ngw...|[5c3da976e4b043d0...|[2019-02-13T16:00...|[2019-01-15T09:35...|     245884266|[181374695, 2, 24...|                 0|[1547544950262]|Wait4Persist|
+--------------------+--------------------+--------------------+--------------------+--------------+--------------------+------------------+---------------+------------+

案例4. Creating DataFrames from JDBC
在项目中加入mysql 的驱动包
  <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>6.0.2</version>
    </dependency>
 val spark = SparkSession.builder().config(conf).getOrCreate();
 val str_url = "jdbc:mysql://localhost:3306/miracleops";
 val table_df = spark.read.format("jdbc").option("driver","com.mysql.jdbc.Driver").option("url",str_url)
      .option("dbtable","user").option("user","root").option("password","root").load();
 table_df.printSchema();
 table_df.select("email","username").show();
输出日志
root
 |-- id: integer (nullable = true)
 |-- password: string (nullable = true)
 |-- last_login: timestamp (nullable = true)
 |-- email: string (nullable = true)
 |-- username: string (nullable = true)
 |-- wechat: string (nullable = true)
 |-- avatar: string (nullable = true)
 |-- job_title: string (nullable = true)
 |-- reg_time: timestamp (nullable = true)
 |-- is_active: boolean (nullable = true)
 |-- is_admin: boolean (nullable = true)
 |-- is_staff: boolean (nullable = true)
 |-- group_id: integer (nullable = true)
 +-------------------+------------+
|              email|    username|
+-------------------+------------+
|Jason.chen@sina.com|       Jason|
|chenxu_0209@163.com|jason.chenTJ|
+-------------------+------------+

### Spark SQLDataFrame 的关系及使用方法 #### 关系分析 Spark SQL 是 Apache Spark 中的一个模块,用于处理结构化数据。它提供了一个编程抽象称为 DataFrame,并作为分布式 SQL 查询引擎的作用[^1]。DataFrame 是一种以表格形式存储的数据结构,类似于传统数据库中的表或者 Pandas 中的 DataFrame。然而,Spark DataFrame 是分布式的,能够在大规模集群上进行高效的并行计算。 Spark SQL 提供了两种主要的方式来操作数据:一是通过 DataFrame API 进行编程式操作;二是通过标准的 SQL 查询语言来进行声明式操作[^2]。这两种方式最终都会被 Catalyst 优化器编译成底层的 RDD 操作,从而保证性能最优。 --- #### 使用方法对比 ##### 1. **DataFrame API** 通过 DataFrame API 可以编写更加灵活和强大的代码逻辑。以下是其特点: - 支持链式调用,便于构建复杂的 ETL 流程。 - 自动利用 Catalyst 优化器对查询计划进行优化。 - 数据不可变且延迟执行,适合批处理场景。 下面是一个简单的例子展示了如何使用 DataFrame API 来完成 WordCount: ```python from pyspark.sql import SparkSession from pyspark.sql.functions import col, split, explode if __name__ == "__main__": spark = SparkSession.builder \ .appName("WordCount") \ .master("local[*]") \ .getOrCreate() # 加载文本文件到 DataFrame df = spark.read.text("/path/to/input/file") # 将每行拆分为单词列表 words_df = df.select(explode(split(col("value"), "\\s+")).alias("word")) # 对每个单词计数 result_df = words_df.groupBy("word").count().orderBy(col("count").desc()) # 展示结果 result_df.show(truncate=False) spark.stop() ``` 此代码片段说明了如何通过 DataFrame API 实现分词、聚合以及排序功能[^4]。 --- ##### 2. **SQL 风格** 对于熟悉 SQL 的用户来说,可以直接注册临时视图并通过 SQL 查询来获取所需的结果。这种方式的优点在于语法简单直观,易于维护。 继续以上述 WordCount 为例,可以改写为如下 SQL 形式: ```python from pyspark.sql import SparkSession if __name__ == "__main__": spark = SparkSession.builder \ .appName("WordCount_SQL") \ .master("local[*]") \ .getOrCreate() # 加载文本文件到 DataFrame创建临时视图 df = spark.read.text("/path/to/input/file") df.createOrReplaceTempView("lines") # 执行 SQL 查询统计单词频率 word_count_df = spark.sql(""" SELECT word, COUNT(*) AS count FROM ( SELECT EXPLODE(SPLIT(value, '\\s+')) AS word FROM lines ) GROUP BY word ORDER BY count DESC """) # 显示前几条记录 word_count_df.show(truncate=False) spark.stop() ``` 上述代码同样实现了基于 SQL 的 WordCount 功能[^5]。 --- #### 联系与区别 | 特性 | DataFrame API | SQL 风格 | |---------------------|---------------------------------------|---------------------------------------| | 编程模型 | 基于 Python 或 Scala 的函数式编程 | 类似传统的 SQL 查询 | | 学习曲线 | 较陡峭 | 如果已有 SQL 基础,则较为平缓 | | 性能 | 同样由 Catalyst 优化 | 同样由 Catalyst 优化 | | 灵活性 | 更加灵活,适用于复杂业务逻辑 | 主要针对固定模式的查询需求 | 两者的核心差异体现在表达方式的不同:前者更适合开发者习惯,而后者则更贴近分析师的需求[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值