spark DataFrame学习手册

spark DataFrame学习手册

本文spark为2.0.0 编程语言为java

概述

Spark SQL 是 Spark 用来处理结构化数据的一个模块。与基础的 Spark RDD API 不同,Spark SQL 提供了更多数据与要执行的计算的信息。在其实现中,会使用这些额外信息进行优化。可以使用 SQL 语句和 Dataset API 来与 Spark SQL 模块交互。无论你使用哪种语言或 API 来执行计算,都会使用相同的引擎。这让你可以选择你熟悉的语言(现支持 Scala、Java、R、Python)以及在不同场景下选择不同的方式来进行计算

SQL

Spark SQL的一种用法是执行SQL查询。Spark SQL也可以用于从已安装的Hive中读取数据。当从内部其他编程语言执行SQL,结果将以Dataset/DataFrame形式返回。你也可以通过command-line或者JDBC/ODBC与SQL接口进行交互。

Datasets和DataFrames

Dataset 是一个分布式数据集合。Dataset 是自 Spark 1.6开始提供的新接口,能同时享受到 RDDs 的优势(强类型,能使用强大的 lambda 函数)以及 Spark SQL 优化过的执行引擎。Dataset 可以从 JVM 对象(s)创建而来并且可以使用各种 transform 操作(比如 map,flatMap,filter 等)。目前 Dataset API 支持 Scala 和 Java。Python 暂不支持 Dataset API。不过得益于 Python 的动态属性,可以享受到许多 DataSet API 的益处。R 也是类似情况。

DataFrame 是具有名字的列。概念上相当于关系数据库中的表或 R/Python 下的 data frame,但有更多的优化。DataFrames(Dataset 亦是如此) 可以从很多数据中构造,比如:结构化文件、Hive 中的表,数据库,已存在的 RDDs。DataFrame API 可在 Scala、Java、Python 和 R 中使用。在 Scala 和 Java 中,DataFrame 由一个元素为 Row 的 Dataset 表示。在 Scala API 中,DataFrame 只是 Dataset[Row] 的别名。在 Java API 中,类型为 Dataset。

Language Main Abstraction
Scala Dataset[T] & DataFrame (alias for Dataset[Row])
Java Dataset
Python* DataFrame
R* DataFrame

在本文剩余篇幅中,会经常使用 DataFrame 来代指 Scala/Java 元素为 Row 的 Dataset。

开始

起始点:SparkSession

SparkSession是spark2.0所有功能的新入口点,代替了原来的SparkContext和其他扩展入口,只需调用

sparkSession.builder()

即可创建

SparkSession spark= SparkSession.builder()
  .master("local")
  .appName("Json")
  .config("spark.sql.warehouse.dir", "file:///E:\\apache\\jartest\\mvndatabase") 
  //此处需要将spark.sql.warehouse.dir指定到本地正确的仓库地址
  .getOrCreate();

创建DataFrames

使用 SparkSession,可以从已经在的 RDD、Hive 表以及 Spark 支持的数据格式创建。

下面这个例子就是读取一个 Json 文件来创建一个 DataFrames

Dataset df=spark.read().json("D://test.json");
df.show();
//结果如下所示
+--------------------+--------------------+--------------------+--------------------+
|     _corrupt_record|         description|                link|               title|
+--------------------+--------------------+--------------------+--------------------+
|                   [|                null|                null|                null|
|  // ActiveRecord...|                null|                null|                null|
|                null|Sets attributes t...|http://api.rubyon...|  create_with(value)|
|                null|Specifies whether...|http://api.rubyon...|distinct(value = ...|
|                null|Forces eager load...|http://api.rubyon...|   eager_load(*args)|
|                null|Used to extend a ...|http://api.rubyon...|extending(*module...|
|                null|Specifies table f...|http://api.rubyon...|from(value, subqu...|
|                null|Allows to specify...|http://api.rubyon...|        group(*args)|
|                null|Allows to specify...|http://api.rubyon...| having(opts, *rest)|
|                null|Specify relations...|http://api.rubyon...|     includes(*args)|
|                null|Performs a joins ...|http://api.rubyon...|        joins(*args)|
|                null|Specifies a limit...|http://api.rubyon...|        limit(value)|
|                null|Specifies locking...|http://api.rubyon...|  lock(locks = true)|
|                null|Returns a chainab...|http://api.rubyon...|              none()|
|                null|Specifies the num...|http://api.rubyon...|       offset(value)|
|                null|Allows to specify...|http://api.rubyon...|        order(*args)|
|                null|Allows preloading...|http://api.rubyon...|      preload(*args)|
|                null|Sets readonly att...|http://api.rubyon...|readonly(value = ...|
|                null|Use to indicate t...|http://api.rubyon...|references(*table...|
|                null|Replaces any exis...|http://api.rubyon...|      reorder(*args)|
+--------------------+--------------------+--------------------+--------------------+
only showing top 20 rows

无类型的Dataset操作(DataFrame)

DataFrame在Scala、Java、Python和R中为结构化数据操作提供了一个特定领域语言支持。       就像网文提到的,在Spark2.0中,在Scala和Java的API中,DataFrame仅仅是Dataset的RowS表示。与Scala/Java中的强类型的“带类型转换操作”相比,这些操作也可以看做“无类型转换操作”。这里我们提供了一些使用Dataset进行结构化数据处理的基本示例:

df.select("title").show();
//结果如下
+--------------------+
|               title|
+--------------------+
|                null|
|                null|
|  create_with(value)|
|distinct(value = ...|
|   eager_load(*args)|
|extending(*module...|
|from(value, subqu...|
|        group(*args)|
| having(opts, *rest)|
|     includes(*args)|
|        joins(*args)|
|        limit(value)|
|  lock(locks = true)|
|              none()|
|       offset(value)|
|        order(*args)|
|      preload(*args)|
|readonly(value = ...|
|references(*table...|
|      reorder(*args)|
+--------------------+
only showing top 20 rows
df.groupBy("title").count().show();
 //结果如下
+--------------------+-----+
|      unscope(*args)|    1|
|        order(*args)|    1|
|      preload(*args)|    1|
|   eager_load(*args)|    1|
|  uniq(value = true)|    1|
| having(opts, *rest)|    1|
|                null|    4|
|        limit(value)|    1|
|     select(*fields)|    1|
|     reverse_order()|    1|
|       PHP����õ�����|    1|
|readonly(value = ...|    1|
|references(*table...|    1|
|distinct(value = ...|    1|
|              none()|    1|
|       offset(value)|    1|
|        joins(*args)|    1|
|extending(*module...|    1|
| rewhere(conditions)|    1|
|  create_with(value)|    1|
+--------------------+-----+
only showing top 20 rows            

编程执行SQL查询语句

 Sparksession中的sql函数使得应用可以编程式执行SQL查询语句并且已DataFrame形式返回:

df.createOrReplaceTempView("test");
Dataset sqlDF=spark.sql("SELECT*FROM test");
sqlDF.show();
+--------------------+--------------------+--------------------+--------------------+
|     _corrupt_record|         description|                link|               title|
+--------------------+--------------------+--------------------+--------------------+
|                   [|                null|                null|                null|
|  // ActiveRecord...|                null|                null|                null|
|                null|Sets attributes t...|http://api.rubyon...|  create_with(value)|
|                null|Specifies whether...|http://api.rubyon...|distinct(value = ...|
|                null|Forces eager load...|http://api.rubyon...|   eager_load(*args)|
|                null|Used to extend a ...|http://api.rubyon...|extending(*module...|
|                null|Specifies table f...|http://api.rubyon...|from(value, subqu...|
|                null|Allows to specify...|http://api.rubyon...|        group(*args)|
|                null|Allows to specify...|http://api.rubyon...| having(opts, *rest)|
|                null|Specify relations...|http://api.rubyon...|     includes(*args)|
|                null|Performs a joins ...|http://api.rubyon...|        joins(*args)|
|                null|Specifies a limit...|http://api.rubyon...|        limit(value)|
|                null|Specifies locking...|http://api.rubyon...|  lock(locks = true)|
|                null|Returns a chainab...|http://api.rubyon...|              none()|
|                null|Specifies the num...|http://api.rubyon...|       offset(value)|
|                null|Allows to specify...|http://api.rubyon...|        order(*args)|
|                null|Allows preloading...|http://api.rubyon...|      preload(*args)|
|                null|Sets readonly att...|http://api.rubyon...|readonly(value = ...|
|                null|Use to indicate t...|http://api.rubyon...|references(*table...|
|                null|Replaces any exis...|http://api.rubyon...|      reorder(*args)|
+--------------------+--------------------+--------------------+--------------------+
only showing top 20 rows

数据源

Spark SQL通过DataFrame接口,可以支持对多种数据源的操作。DataFrame可以使用关系转换来进行操作,而且可以用来创建临时视图。将DataFrame注册为临时视图可以允许你在数据上运行SQL查询语句。本节讲解使用SparkData Source加载数据和保存数据的通用方法,然后详细讲述内部支持的数据源可用的特定操作。

通用Load/Save函数

最简单的,默认的数据源(parquet,除非使用spark.sql.sources.default进行了配置)将被用于所有的操作

Dataset usersDF = spark.read().load("examples/src/main/resources/users.parquet");
usersDF.select("name", "favorite_color").write().save("namesAndFavColors.parquet");

手动指定选项

你可以手动指定数据源以及数据源附带的额外选项。数据源被他们的完全限定名来指定(如,org.apache.spark.sql.parquet),但对于内部支持的数据源,你可以使用短名(json,parquet,jdbc)。DataFrame可以使用这种语法从任何可以转换为其他类型的数据源加载数据。

Dataset peopleDF =
  spark.read().format("json").load("examples/src/main/resources/people.json");
peopleDF.select("name", "age").write().format("parquet").save("namesAndAges.parquet");

在文件上直接执行SQL

除了使用读取API加载一个文件到SATAFrame然后查询它的方式,你同样可以通过SQL直接查询文件。

Dataset sqlDF 
=spark.sql("SELECT * FROM parquet.`examples/src/main/resources/users.parquet`");

JSON数据集

Spark SQL可以自动推断JSON数据集的schema并且加载为Dataset[Row]。可以对String类型的RDD或者JSON文件使用SparkSession.read.json()来实现这种转换。
 注意这里的JSON文件不是通常意义的JSON文件。每一行必须包含分离的,完整有效的JSON对象。因此,不支持常用的多行式JSON文件。

1.读入JSON文件
Dataset people = spark.read().json("examples/src/main/resources/people.json");
people.createOrReplaceTempView("people");
Dataset namesDF = spark.sql("SELECT name FROM people WHERE age BETWEEN 13 AND 19");
namesDF.show();
2.手动创建JSON格式的数组
List jsonData = Arrays.asList(
        "{\"name\":\"Yin\",\"address\":{\"city\":\"Columbus\",\"state\":\"Ohio\"}}");
Dataset anotherPeopleDataset = spark.createDataset(jsonData, Encoders.STRING());
Dataset anotherPeople = spark.read().json(anotherPeopleDataset);
anotherPeople.show();

你可能感兴趣的:(大数据,Java)