Spark中文文档翻译3.1.1-Spark SQL Guide--Getting Started

如果觉得内容不错,别忘记一键三连哦!!!
如果觉得内容不错,别忘记一键三连哦!!!
如果觉得内容不错,别忘记一键三连哦!!!

Getting Started

Starting Point: SparkSession

Spark中所有功能的入口点都是SparkSession类。要创建基本的SparkSession,只需使用SparkSession.builder()

import org.apache.spark.sql.SparkSession

val spark: SparkSession = SparkSession
  .builder()
  .appName("Spark SQL basic example")
  .config("spark.some.config.option", "some-value")
  .getOrCreate()

在Spark存储库中的“ examples / src / main / scala / org / apache / spark / examples / sql / SparkSQLExample.scala”中找到完整的示例代码。

Spark 2.0中的SparkSession为Hive功能提供了内置支持,包括使用HiveQL编写查询的能力,对Hive UDF的访问以及从Hive表读取数据的能力。 要使用这些功能,您不需要现有的Hive设置。

Creating DataFrames

使用SparkSession,应用程序可以从现有的RDD、Hive表或Spark数据源创建DataFrame 。以基于JSON文件内容创建一个DataFrame 为例

val df: DataFrame  = spark.read.json("examples/src/main/resources/people.json")

// Displays the content of the DataFrame to stdout
df.show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

在Spark存储库中的“ examples / src / main / scala / org / apache / spark / examples / sql / SparkSQLExample.scala”中找到完整的示例代码。

Untyped Dataset Operations (aka DataFrame Operations

DataFrames为Scala、Java、Python和R中的结构化数据操作提供了一种特定于领域的语言。

如上所述,在Spark 2.0中,DataFrame只是Scala和Java API中的Dataset of Rows。 与强类型的Scala / Java数据集附带的“类型转换”相反,这些操作也称为“非类型转换”。

这里我们包括一些使用Datasets进行结构化数据处理的基本例子

// This import is needed to use the $-notation
import spark.implicits._
// Print the schema in a tree format
df.printSchema()
// root
// |-- age: long (nullable = true)
// |-- name: string (nullable = true)

// Select only the "name" column
df.select("name").show()
// +-------+
// |   name|
// +-------+
// |Michael|
// |   Andy|
// | Justin|
// +-------+

// Select everybody, but increment the age by 1
df.select($"name", $"age" + 1).show()
// +-------+---------+
// |   name|(age + 1)|
// +-------+---------+
// |Michael|     null|
// |   Andy|       31|
// | Justin|       20|
// +-------+---------+

// Select people older than 21
df.filter($"age" > 21).show()
// +---+----+
// |age|name|
// +---+----+
// | 30|Andy|
// +---+----+

// Count people by age
df.groupBy("age").count().show()
// +----+-----+
// | age|count|
// +----+-----+
// |  19|    1|
// |null|    1|
// |  30|    1|
// +----+-----+

在Spark存储库中的“ examples / src / main / scala / org / apache / spark / examples / sql / SparkSQLExample.scala”中找到完整的示例代码。

有关可以对dataSet执行的操作类型的完整列表,请参阅API文档。

除了简单的列引用和表达式之外,dataSet还有一个丰富的函数库,包括字符串操作、数据运算、常见的数学运算等等。完整的列表可以在DataFrame函数参考中找到。

Running SQL Queries Programmatically(以编程方式运行SQL查询)

SparkSession上的sql函数允许应用程序以编程方式运行sql查询,并将结果作为DataFrame返回。

// Register the DataFrame as a SQL temporary view
df.createOrReplaceTempView("people")

val sqlDF = spark.sql("SELECT * FROM people")
sqlDF.show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

Global Temporary View(全局临时视图)

Spark SQL中的临时视图是会话范围的,如果创建临时视图的会话终止,临时视图就会消失。如果您希望拥有一个在所有会话之间共享的临时视图,并在Spark应用程序终止之前保持活动状态,那么可以创建一个全局临时视图。全局临时视图绑定到一个系统保留的数据库global_temp,我们必须使用限定名来引用它,例如SELECT * FROM global_temp.view1.

// Register the DataFrame as a global temporary view
df.createGlobalTempView("people")

// Global temporary view is tied to a system preserved database `global_temp`
spark.sql("SELECT * FROM global_temp.people").show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

// Global temporary view is cross-session
spark.newSession().sql("SELECT * FROM global_temp.people").show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

Creating Datasets

Datasets 与RDD相似,但是,它们不使用Java serialization or Kryo,而是使用专用的Encoder对对象进行序列化以进行网络处理或传输。 虽然编码器和标准序列化都负责将对象转换为字节,但是编码器是动态生成的代码,并使用一种格式,该格式允许Spark执行许多操作,例如过滤,排序和哈希处理,而无需将字节反序列化回对象。

case class Person(name: String, age: Long)

// Encoders are created for case classes
val caseClassDS: Dataset[Person] = Seq(Person("Andy", 32)).toDS()
caseClassDS.show()
// +----+---+
// |name|age|
// +----+---+
// |Andy| 32|
// +----+---+

// Encoders for most common types are automatically provided by importing spark.implicits._
val primitiveDS: Dataset[Int] = Seq(1, 2, 3).toDS()
primitiveDS.map(_ + 1).collect() // Returns: Array(2, 3, 4)

// DataFrames can be converted to a Dataset by providing a class. Mapping will be done by name
val path = "examples/src/main/resources/people.json"
val peopleDS = spark.read.json(path).as[Person]
peopleDS.show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+

Interoperating with RDDs

Spark SQL支持两种不同的方法来将现有的RDDs转换为Datasets。第一种方法使用反射来推断包含特定类型对象的RDD的schema 。这种基于反射的方法可以使代码更简洁,并且在编写Spark应用程序时,如果您已经了解了schema ,这种方法就可以很好地工作。

创建Datasets 的第二种方法是通过一个编程接口,该接口允许您构造一个schema ,然后将其应用到现有的RDD。虽然此方法更详细,但它允许在运行时才知道列及其类型时构造Datasets 。

Inferring the Schema Using Reflection

Spark SQL的Scala接口支持自动将包含case类的RDD转换为DataFrame。case类定义表的schema 。使用反射读取case类的参数名称,并成为列的名称。Case类也可以是嵌套的,或者包含复杂类型,比如Seqs or Arrays。这个RDD可以隐式转换为一个DataFrame ,然后注册为一个表。表可以在后续的SQL语句中使用。

// For implicit conversions from RDDs to DataFrames
import spark.implicits._

// Create an RDD of Person objects from a text file, convert it to a Dataframe
val peopleDF:DataFrame = spark.sparkContext                               :SparkComtext
  .textFile("examples/src/main/resources/people.txt")                     :RDD[String]
  .map(_.split(","))                                                      :RDD[Array[String]]
  .map(attributes => Person(attributes(0), attributes(1).trim.toInt))     :RDD[Person]
  .toDF()                                                                 :DataFrame
// Register the DataFrame as a temporary view
peopleDF.createOrReplaceTempView("people")

// SQL statements can be run by using the sql methods provided by Spark
val teenagersDF = spark.sql("SELECT name, age FROM people WHERE age BETWEEN 13 AND 19")

// The columns of a row in the result can be accessed by field index
teenagersDF.map(teenager => "Name: " + teenager(0)).show()
// +------------+
// |       value|
// +------------+
// |Name: Justin|
// +------------+

// or by field name
teenagersDF.map(teenager => "Name: " + teenager.getAs[String]("name")).show()
// +------------+
// |       value|
// +------------+
// |Name: Justin|
// +------------+

// No pre-defined encoders for Dataset[Map[K,V]], define explicitly
implicit val mapEncoder = org.apache.spark.sql.Encoders.kryo[Map[String, Any]]
// Primitive types and case classes can be also defined as
// implicit val stringIntMapEncoder: Encoder[Map[String, Any]] = ExpressionEncoder()

// row.getValuesMap[T] retrieves multiple columns at once into a Map[String, T]
teenagersDF.map(teenager => teenager.getValuesMap[Any](List("name", "age"))).collect()
// Array(Map("name" -> "Justin", "age" -> 19))

Programmatically Specifying the Schema

当不能提前定义case类时(例如,记录的结构以字符串编码,或者文本数据集将被解析,字段将针对不同的用户进行不同的投影),可以通过三个步骤以编程方式创建数据框架。

1、从原始RDD创建一个Row组成的RDD

2、创建与步骤1中创建的RDD中的行结构相匹配的StructType表示的schema 。

3、通过SparkSession提供的createDataFrame方法将schema 应用到Row的RDD。

import org.apache.spark.sql.Row

    import org.apache.spark.sql.types._

    // Create an RDD
    val peopleRDD: RDD[String] = spark.sparkContext.textFile("examples/src/main/resources/people.txt")

    // The schema is encoded in a string
    val schemaString: String = "name age"

    // Generate the schema based on the string of schema
    val fields: Array[StructField] = schemaString.split(" ")
      .map(fieldName => StructField(fieldName, StringType, nullable = true))
    val schema: StructType = StructType(fields)

    // Convert records of the RDD (people) to Rows
    val rowRDD: RDD[Row] = peopleRDD
      .map(_.split(","))
      .map(attributes => Row(attributes(0), attributes(1).trim))

    // Apply the schema to the RDD
    val peopleDF: DataFrame = spark.createDataFrame(rowRDD, schema)

    // Creates a temporary view using the DataFrame
    peopleDF.createOrReplaceTempView("people")

    // SQL can be run over a temporary view created using DataFrames
    val results: DataFrame = spark.sql("SELECT name FROM people")

    // The results of SQL queries are DataFrames and support all the normal RDD operations
    // The columns of a row in the result can be accessed by field index or by field name
    results.map(attributes => "Name: " + attributes(0)).show()
    // +-------------+
    // |        value|
    // +-------------+
    // |Name: Michael|
    // |   Name: Andy|
    // | Name: Justin|
    // +-------------+

Scalar Functions

scala函数是每行返回一个值的函数,而聚合函数则返回一组行的值。Spark SQL支持各种内置标量函数。它还支持用户定义的scala函数。

Aggregate Functions

聚合函数是在一组行上返回单个值的函数。内置的聚合函数提供了常见的聚合,如count()、countDistinct()、avg()、max()、min()等。用户不受预定义聚合函数的限制,可以创建自己的聚合函数。有关用户自定义聚合函数的详细信息,请参阅用户自定义聚合函数的文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值