一、Spark SQL 概述

1.1 什么是Spark SQL

Spark SQLSpark 用来处理结构化数据的一个模块,它提供了2个编程抽象:

DataFrameDataSet,并且作为分布式 SQL 查询引擎的作用。

Hive 作为对比,Hive 是将 Hive SQL 转换成 MapReduce 然后提交到集群上执行,大大简化了编写 MapReduce 的程序的复杂性,由于 MapReduce 这种计算模型执行效率比较慢。所有Spark SQL 的应运而生,它是将 Spark SQL 转换成 RDD,然后提交到集群执行,执行效率非常快。

1.2 Spark SQL 的特点

这里引用 Spark 官网:

① 易整合

② 统一的数据访问方式

③ 兼容Hive

④ 标准的数据连接

1.3 什么是 DataFrame

Spark 中,DataFrame 是一种以 RDD 为基础的分布式数据集,类似于传统数据库中的二维表格。

DataFrameRDD 的主要区别在于,前者带有 schema 元信息,即 DataFrame 所表示的二维表数据集的每一列都带有名称和类型。这使得 Spark SQL 得以洞察更多的结构信息,从而对藏于DataFrame 背后的数据源以及作用于 DataFrame 之上的变换进行了针对性的优化,最终达到大幅提升运行时效率的目标。

反观 RDD,由于无从得知所存二维数据的内部结构,Spark Core 只能在 stage 层面进行简单、通用的流水线优化。

图示

DataFrame 也是懒执行的,但性能上比 RDD 要高,主要原因:

优化的执行计划,即查询计划通过 Spark Catalyst Optimiser 进行优化。比如下面一个例子:

看看 Spark CoreSpark SQL 模块对这个计划的执行步骤:

1.4 什么是 DataSet

DataSet 也是分布式数据集合。

DataSetSpark 1.6 中添加的一个新抽象,是 DataFrame 的一个扩展。它提供了 RDD 的优势(强类型,使用强大的 Lambda 函数的能力)以及 Spark SQL 优化执行引擎的优点,DataSet 也可以使用功能性的转换(操作 mapflatMapfilter 等等)。

具体的优势如下:

1)是 DataFrame API 的一个扩展,SparkSQL 最新的数据抽象;

2)用户友好的 API 风格,既具有类型安全检查也具有 DataFrame 的查询优化特性;

3)用样例类来对 DataSet 中定义数据的结构信息,样例类中每个属性的名称直接映射到 DataSet 中的字段名称;

4)DataSet 是强类型的。比如可以有 DataSet[Car]DataSet[Person]

二、Spark SQL 编程

2.1 SparkSession

在老的版本中,Spark SQL 提供两种 SQL 查询起始点:一个叫 SQLContext,用于 Spark 自己提供的 SQL 查询;一个叫 HiveContext,用于连接 Hive 的查询。

SparkSessionSpark 最新的 SQL 查询起始点,实质上是 SQLContextHiveContext 的组合,所以在 SQLContexHiveContext 上可用的 APISparkSession 上同样是可以使用的。

SparkSession 内部封装了 SparkContext,所以计算实际上是由 SparkContext 完成的。

2.2 DataFrame

1. 创建

Spark SQLSparkSession 是创建 DataFrame 和执行 SQL 的入口,创建 DataFrame 有三种方式

  1. 通过 Spark 的数据源进行创建;
  2. 从一个存在的 RDD 进行转换;
  3. 还可以从 Hive Table 进行查询返回
通过 Spark 的数据源进行创建
  • 查看 Spark 数据源进行创建的文件格式
  • 读取官网提供的 json 文件创建 DataFrame
  • RDD 转换(详见 2.5 节)
  • Hive Table 转换(详见 3.3节)

2. SQL 风格语法(主要)

直接通过 SQL 语句对 DataFrame 的数据进行操作

  1. 创建一个 DataFrame
  1. DataFrame 创建一个临时表

创建临时表的三种方式

  1. 通过 SQL 语句实现查询全表

注意:普通临时表是 Session 范围内的,如果想应用范围内有效,可以使用全局临时表。使用全局临时表时需要全路径访问,如:global_temp.people

  1. 对于 DataFrame 创建一个全局表
df.createGlobalTempView("people")
复制代码
  1. 通过 SQL 语句实现查询全表
spark.sql("SELECT * FROM global_temp.people").show()
复制代码
 spark.newSession().sql("SELECT * FROM global_temp.people").show()
复制代码

以上两行代码的执行效果一致~

3. DSL 风格语法(次要)

使用更为简洁的语法对 DataFrame 的数据操作

  1. 创建一个 DataFrame(同上)

  2. 查看 DataFrameSchema 信息

  1. 只查看 name 列数据
  1. 查看 name 列数据以及 age+1 数据
  1. 查看 age 大于 21 的数据
  1. 按照 age 分组,查看数据条数

个人感觉简单的操作可以使用 DSL,复杂查询再使用 SQL 是一个很不错的方案

注意:DSL 方法由 DataFrame 调用,而 SQLSparkSession 调用

4. RDD 转换为 DateFrame

注意:如果需要 RDDDF 或者 DS 之间操作,那么都需要引入 import spark.implicits._ 【spark不是包名,而是 SparkSession 对象的名称】

前置条件:导入隐式转换并创建一个 RDD

  1. 通过手动确定转换
  1. 通过反射确定(需要用到样例类)

    • 创建一个样例类
    case class People(name:String, age:Int)
    复制代码
    • 根据样例类将 RDD 转换为 DataFrame
  1. 通过编程方式(了解)
  • 导入所需的类型
 import org.apache.spark.sql.types._
复制代码
  • 创建 Schema
val structType: StructType = StructType(StructField("name", StringType) :: StructField("age", IntegerType) :: Nil)
复制代码
  • 导入所需的类型
import org.apache.spark.sql.Row
复制代码
  • 根据给定的类型创建二元组 RDD
val data = rdd.map{ x => val para = x.split(",");Row(para(0),para(1).trim.toInt)}
复制代码
  • 根据数据及给定的 schema 创建 DataFrame
val dataFrame = spark.createDataFrame(data, structType)
复制代码

5. DateFrame 转换为 RDD

2.3 DataSet

DataSet 是具有强类型的数据集合,需要提供对应的类型信息。

DataSet 的创建可以直接使用 Seq 静态方法创建 或者 RDD 转换 或者 DataFrame 转换

1. 创建

  1. 创建一个样例类
case class Person(name: String, age: Long)
复制代码
  1. 创建 DataSet

2. RDD 转换为 DataSet

Spark SQL 能够自动将包含有 case 类的 RDD 转换成 DataFramecase 类定义了 table 的结构,case 类属性通过反射变成了表的列名。case 类可以包含诸如 Seqs 或者 Array 等复杂的结构。

  1. 创建一个 RDD
  2. 创建一个样例类
case class Person(name: String, age: Int)
复制代码
  1. RDD 转化为 DataSet

3. DataSet 转换为 RDD

2.4 DataFrame与DataSet的互操作

1. DataFrame 转 Dataset

  1. 创建一个 DateFrame
  1. 创建一个样例类并转换

2. Dataset 转 DataFrame

  1. 创建一个样例类(同上)
  2. 创建 DataSet
val ds = Seq(Person("Andy", 32)).toDS()
复制代码
  1. DataSet 转化为 DataFrame
val df = ds.toDF
复制代码

使用 as 方法,转成 Dataset,这在数据类型是 DataFrame 又需要针对各个字段处理时极为方便。在使用一些特殊的操作时,一定要加上 import spark.implicits._ 不然 toDFtoDS 无法使用。

2.5 RDD,DataFrame,DataSet

Spark SQLSpark 为我们提供了两个新的抽象,分别是 DataFrameDataSet。他们和 RDD 有什么区别呢?首先从版本的产生上来看:

RDD (Spark1.0) —> Dataframe(Spark1.3) —> Dataset(Spark1.6)

如果同样的数据都给到这三个数据结构,他们分别计算之后,都会给出相同的结果。不同是的他们的执行效率和执行方式。在后期的 Spark 版本中,DataSet 有可能会逐步取代 RDDDataFrame成为唯一的 API 接口。

1. 三者的共性

(1)RDDDataFrameDataset 全都是 spark 平台下的分布式弹性数据集,为处理超大型数据提供便利;

(2)三者都有惰性机制,在进行创建、转换,如 map 方法时,不会立即执行,只有在遇到 Actionforeach 时,三者才会开始遍历运算;

(3)三者有许多共同的函数,如 filter排序 等;

(4)在对 DataFrameDataset 进行操作许多操作都需要这个包:import spark.implicits._(在创建好 SparkSession 对象后尽量直接导入)

这里给出关于这三者讲解比较深入的文章

2. 三者的转换

2.6 IDEA 创建 Spark SQL 程序

通过一个简单的案例快速入手如何在 IDEA 上开发 Spark SQL 程序

导入以下依赖

<dependencies><dependency><groupId>org.apache.spark</groupId><artifactId>spark-sql_2.11</artifactId><version>2.1.1</version></dependency>
</dependencies>
复制代码

代码实现

object Main2 {def main(args: Array[String]): Unit = {val session: SparkSession = SparkSession.builder().appName("spark sql").master("local[*]").getOrCreate()import session.implicits._val dataFrame: DataFrame = session.read.json("/home/cris/people.json")//打印dataFrame.show()//DSL风格:查询年龄在21岁以上的dataFrame.filter($"age" > 21).show()//创建临时表dataFrame.createOrReplaceTempView("persons")//SQL风格:查询年龄在21岁以上的session.sql("SELECT * FROM persons where age > 21").show()//关闭连接session.stop()}
}
复制代码

无法找到主类

如果在执行 Scala 或者是 java 程序中,报无法找到主类执行的异常,可能是项目的结构有问题,将父模块直接移除掉,然后重新导入父模块即可

2.7 用户自定义函数

1. 用户自定义 UDF 函数

object MyFunc {def main(args: Array[String]): Unit = {val session: SparkSession = SparkSession.builder().appName("spark sql").master("local[*]").getOrCreate()val dataFrame: DataFrame = session.read.json("/home/cris/people.json")/*用户自定义 UDF 函数*/session.udf.register("addName", (x: String) => {"cool:" + x})dataFrame.createOrReplaceTempView("people")session.sql("select addName(name),age from people").show()session.stop()}
}
复制代码

结果如下

2. 用户自定义 UDAF 函数

强类型的 Dataset 和弱类型的 DataFrame 都提供了相关的聚合函数, 如 count()countDistinct()avg()max()min()

除此之外,用户可以设定自己的自定义聚合函数。通过继承 UserDefinedAggregateFunction 来实现用户自定义聚合函数

/*** 定义自己的 UDAF 函数** @author cris* @version 1.0**/
object MyFunc extends UserDefinedAggregateFunction {// 聚合函数输入参数的数据类型override def inputSchema: StructType = StructType(StructField("inputField", LongType) :: Nil)// 聚合缓冲区中值得数据类型override def bufferSchema: StructType = {StructType(StructField("sum", LongType) :: StructField("count", LongType) :: Nil)}// 返回值的数据类型override def dataType: DataType = DoubleType// 对于相同的输入是否一直返回相同的输出override def deterministic: Boolean = true// 初始化override def initialize(buffer: MutableAggregationBuffer): Unit = {// 工资的总额buffer(0) = 0L// 员工人数buffer(1) = 0L}// 相同 Executor 间的数据合并override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {buffer(0) = buffer.getLong(0) + input.getLong(0)buffer(1) = buffer.getLong(1) + 1}// 不同 Executor 间的数据合并override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {buffer1(0) = buffer1.getLong(0) + buffer2.getLong(0)buffer1(1) = buffer1.getLong(1) + buffer2.getLong(1)}// 最终函数计算的返回值override def evaluate(buffer: Row): Double = {buffer.getLong(0).toDouble / buffer.getLong(1)}
}
复制代码

测试代码

object MyFuncTest2 {def main(args: Array[String]): Unit = {val session: SparkSession = SparkSession.builder().appName("spark sql").master("local[*]").getOrCreate()val dataFrame: DataFrame = session.read.json("/home/cris/employees.json")session.udf.register("avg", MyFunc)dataFrame.createTempView("emp")session.sql("select avg(salary) as avg_sal from emp").show()session.stop()}
}
复制代码

测试如下

三、Spark SQL 数据的加载与保存

3.1 通用加载/保存方法

1. 加载数据

  • 通过 read 方法直接加载数据
scala> spark.read.
csv  jdbc   json  orc   parquet textFile… …
复制代码

注意:加载数据的相关参数需写到上述方法中。如:textFile 需传入加载数据的路径,jdbc 需传入 JDBC 相关参数

  • format 方法(了解)
scala> spark.read.format("…")[.option("…")].load("…")
复制代码

用法详解:

(1)format("…"):指定加载的数据类型,包括"csv"、"jdbc"、"json"、"orc"、"parquet"和"textFile"。

(2)load("…"):在"csv"、"orc"、"parquet"和"textFile"格式下需要传入加载数据的路径。

(3)option("…"):在"jdbc"格式下需要传入JDBC相应参数,url、user、password和dbtable

2. 保存数据

  • write 直接保存数据
scala> df.write.
csv  jdbc   json  orc   parquet textFile… …
复制代码

注意:保存数据的相关参数需写到上述方法中。如:textFile 需传入加载数据的路径,jdbc 需传入 JDBC 相关参数

  • format 指定保存数据类型(了解)
scala> df.write.format("…")[.option("…")].save("…")
复制代码

用法详解:

(1)format("…"):指定保存的数据类型,包括"csv"、"jdbc"、"json"、"orc"、"parquet"和"textFile"。

(2)save ("…"):在"csv"、"orc"、"parquet"和"textFile"格式下需要传入保存数据的路径。

(3)option("…"):在"jdbc"格式下需要传入JDBC相应参数,url、user、password和dbtable

3. 最佳示例代码

object Main2 {def main(args: Array[String]): Unit = {val session: SparkSession = SparkSession.builder().appName("spark sql").master("local[*]").getOrCreate()val dataFrame: DataFrame = session.read.json("/home/cris/people.json")//创建临时表dataFrame.createOrReplaceTempView("persons")//SQL风格:查询年龄在21岁以上的val frame: DataFrame = session.sql("SELECT * FROM persons where age > 21")frame.show()frame.write.json("/home/cris/output")//关闭连接session.stop()}
}
复制代码

执行效果

4. 文件保存选项

可以采用SaveMode执行存储操作,SaveMode 定义了对数据的处理模式。SaveMode 是一个枚举类,其中的常量包括:

(1)Append:当保存路径或者表已存在时,追加内容;

(2)Overwrite: 当保存路径或者表已存在时,覆写内容;

(3)ErrorIfExists:当保存路径或者表已存在时,报错;

(4)Ignore:当保存路径或者表已存在时,忽略当前的保存操作

使用如下

df.write.mode(SaveMode.Append).save("… …")
复制代码

记得保存选项放在 save 操作之前执行

5. 默认数据源

Spark SQL 的默认数据源为 Parquet 格式。数据源为 Parquet 文件时,Spark SQL 可以方便的执行所有的操作。修改配置项 spark.sql.sources.default,可修改默认数据源格式。

  1. 加载数据
val df = spark.read.load("./examples/src/main/resources/users.parquet")
复制代码
  1. 保存数据
df.select("name", " color").write.save("user.parquet")
复制代码

3.2 JSON 文件

Spark SQL 能够自动推测 JSON 数据集的结构,并将它加载为一个 Dataset[Row]. 可以通过 SparkSession.read.json() 去加载一个 一个 JSON 文件。

注意:这个JSON文件不是一个传统的JSON文件,每一行都得是一个JSON串。格式如下:

{"name":"Michael"}
{"name":"Andy", "age":30}
{"name":"Justin", "age":19}
复制代码

Spark-Shell 操作如下:

  1. 导入隐式转换
import spark.implicits._
复制代码
  1. 加载 JSON 文件
val path = "examples/src/main/resources/people.json"
val peopleDF = spark.read.json(path)
复制代码
  1. 创建临时表
peopleDF.createOrReplaceTempView("people")
复制代码
  1. 数据查询
val teenagerNamesDF = spark.sql("SELECT name FROM people WHERE age BETWEEN 13 AND 19")
teenagerNamesDF.show()
+------+
|  name|
+------+
|Justin|
+------+
复制代码

3.3 MySQL

Spark SQL 可以通过 JDBC 从关系型数据库中读取数据的方式创建 DataFrame,通过对 DataFrame 一系列的计算后,还可以将数据再写回关系型数据库中。

可在启动 shell 时指定相关的数据库驱动路径,或者将相关的数据库驱动放到 Spark 的类路径下(推荐)。

以 Spark-Shell 为例

  1. 启动 Spark-Shell
[cris@hadoop101 spark-local]$ bin/spark-shell --master spark://hadoop101:7077 [--jars mysql-connector-java-5.1.27-bin.jar]
复制代码

建议将 MySQL 的驱动直接放入到 Spark 的类(jars)路径下,就不用每次进入 Spark-Shell 带上 --jar 参数了

  1. 定义 JDBC 相关参数配置信息
val connectionProperties = new Properties()
connectionProperties.put("user", "root")
connectionProperties.put("password", "000000")
复制代码
  1. 使用 read.jdbc 加载参数
val jdbcDF2 = spark.read.jdbc("jdbc:mysql://hadoop102:3306/spark", "person", connectionProperties)
复制代码
  1. 或者使用 format 形式加载配置参数(不推荐)
val jdbcDF = spark.read.format("jdbc").option("url", "jdbc:mysql://hadoop102:3306/spark").option("dbtable", " person").option("user", "root").option("password", "000000").load()
复制代码
  1. 使用 write.jdbc 保存数据(可以使用文件保存选项)
jdbcDF2.write.mode(org.apache.spark.sql.SaveMode.Append).jdbc("jdbc:mysql://hadoop102:3306/spark", "person", connectionProperties)
复制代码
  1. 或者使用 format 形式保存数据(不推荐)
jdbcDF.write
.format("jdbc")
.option("url", "jdbc:mysql://hadoop102:3306/spark")
.option("dbtable", "person")
.option("user", "root")
.option("password", "000000")
.save()
复制代码

以 IDEA 操作为例

  1. pom.xml 导入 MySQL 驱动依赖
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency>
复制代码
  1. MySQL 表数据
  1. IDEA 操作代码如下
/*** IDEA 测试 Spark SQL 连接远程的 MySQL 获取数据和写入数据** @author cris* @version 1.0**/
object MysqlTest {def main(args: Array[String]): Unit = {// 获取 SparkSessionval session: SparkSession = SparkSession.builder().appName("spark sql").master("local[*]").getOrCreate()// 设置配置参数val properties = new Properties()properties.put("user", "root")properties.put("password", "000000")// 从 MySQL 获取数据,show() 方法实际调用的是 show(20),默认显示 20 行数据val dataFrame: DataFrame = session.read.jdbc("jdbc:mysql://hadoop102:3306/spark?characterEncoding=UTF-8", "person", properties)dataFrame.show()// 修改并保存数据到 MySQLdataFrame.write.mode(SaveMode.Append).jdbc("jdbc:mysql://hadoop102:3306/spark?characterEncoding=UTF-8", "person", properties)session.stop()}
}
复制代码

注意:防止中文乱码,url 加上 ?characterEncoding=UTF-8 ;写入数据最好指定保存模式 SaveMode

测试如下:

3.4 Hive

Apache HiveHadoop 上的 SQL 引擎,Spark SQL 编译时可以包含 Hive 支持,也可以不包含。包含 Hive 支持的 Spark SQL 可以支持 Hive 表访问、UDF(用户自定义函数)以及 Hive 查询语言(HQL)等。Spark-Shell 默认是Hive支持的;代码中是默认不支持的,需要手动指定(加一个参数即可)。

内置 Hive (了解)

如果要使用内嵌的 Hive,直接用就可以了。

  • 简单创建表

指定路径下就会生成该表的文件夹

  • 导入文件为表数据

在当前 Spark-local 路径下,创建文件 bb

1
2
3
4
5
复制代码

然后创建表,导入数据

查询也没有问题

对应目录下也生成了 bb 表的文件夹

外置 Hive(重要)

如果想连接外部已经部署好的 Hive,需要通过以下几个步骤:

  1. Hive 中的 hive-site.xml 拷贝或者软连接到 Spark 安装目录下的 conf 目录下
[cris@hadoop101 spark-local]$ cp /opt/module/hive-1.2.1/conf/hive-site.xml ./conf/
复制代码
  1. JDBC 的驱动包放置在 Spark.jars 目录下,启动 Spark-Shell
[cris@hadoop101 spark-local]$ cp /opt/module/mysql-libs/mysql-connector-java-5.1.27/mysql-connector-java-5.1.27-bin.jar ./jars/
复制代码

可以通过 Hive 的客户端创建一张表 users

hive> create table users(id int, name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
复制代码

并导入数据

hive> load data local inpath './user.txt' into users;
复制代码

此时 HDFS 显示数据导入成功

Spark-Shell 窗口查看

执行 Hive 的查询语句

可以在 Spark-Shell 执行所有的 Hive 语句,并且执行流程走的是 Spark,而不是 MapReduce

运行Spark SQL CLI

Spark SQL CLI 可以很方便的在本地运行 Hive 元数据服务以及从命令行执行查询任务。在 Spark 目录下执行如下命令启动 Spark SQL CLI,直接执行 SQL 语句,类似一个 Hive 窗口。

[cris@hadoop101 spark-local]$ bin/spark-sql
复制代码

如果使用这种模式进行测试,最好将 log4j 的日志级别设置为 error,否则会有很多 info 级别的日志输出

IDEA 测试 Spark 和 Hive 配合(重要)

首先 pom.xml 引入 Hive 依赖

        <dependency><groupId>org.apache.spark</groupId><artifactId>spark-hive_2.11</artifactId><version>2.1.1</version></dependency><dependency><groupId>org.apache.hive</groupId><artifactId>hive-exec</artifactId><version>1.2.1</version></dependency>
复制代码

然后将 Hive 的配置文件 hive-site.xml 放入 resource 路径下

hive-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration><property><name>javax.jdo.option.ConnectionURL</name><value>jdbc:mysql://hadoop102:3306/metastore?createDatabaseIfNotExist=true</value><description>JDBC connect string for a JDBC metastore</description></property><property><name>javax.jdo.option.ConnectionDriverName</name><value>com.mysql.jdbc.Driver</value><description>Driver class name for a JDBC metastore</description></property><property><name>javax.jdo.option.ConnectionUserName</name><value>root</value><description>username to use against metastore database</description></property><property><name>javax.jdo.option.ConnectionPassword</name><value>000000</value><description>password to use against metastore database</description></property><property><name>hive.cli.print.header</name><value>true</value></property><property><name>hive.cli.print.current.db</name><value>true</value></property><property><name>hive.zookeeper.quorum</name><value>hadoop101,hadoop102,hadoop103</value><description>The list of ZooKeeper servers to talk to. This is only needed for read/write locks.</description></property><property><name>hive.zookeeper.client.port</name><value>2181</value><description>The port of ZooKeeper servers to talk to. This is only needed for read/write locks.</description></property>
</configuration>
复制代码

具体的配置介绍这里不再赘述,可以参考我的 Hive 笔记

测试代码如下:

/*** IDEA 测试 Spark SQL 和 Hive 的联动** @author cris* @version 1.0**/
object HiveTest {def main(args: Array[String]): Unit = {// 注意开启 enableHiveSupportval session: SparkSession = SparkSession.builder().enableHiveSupport().appName("spark sql").master("local[*]").getOrCreate()session.sql("show tables").show()// 注意关闭 session 连接session.stop()}
}
复制代码

执行结果如下

正好就是刚才创建的 Hive

IDEA 自动换行设置

CrisIDEA 设置一行字数最多 120,否则就自动换行,大大提高阅读的舒适感和编码的规范性

设置参考

Deepin 的 Terminal 右键复制

因为 Cris 使用的是 Linux 桌面系统 Deepin,所以经常使用自带的 Terminal 连接远程服务器,这里给出快速右键复制 Terminal 内容的设置

设置参考

Typora 的快捷键自定义设置

因为 Cris 之前使用的是 MacBook,输入法搜狗会很智能的为输入的英文进行前后空格分割,换了 Deepin 后,自带的虽然也是搜狗输入法,但是没有对英文自动空格分割的功能了,后面想想办法,看怎么解决~

因为要对英文和重要内容进行突出显示,Typora 中设置 code 的快捷键默认为 Ctrl+Shift+`,比较麻烦,网上找了找自定义快捷键的设置,最后设置成 Ctrl+C

设置参考

Cris 的 Spark SQL 笔记相关推荐

  1. Cris 的 Spark Streaming 笔记

    一.Spark Streaming 概述 1.1 Spark Streaming是什么 Spark Streaming用于流式数据的处理.Spark Streaming支持的数据输入源很多,例如:Ka ...

  2. Spark SQL 笔记(16)—— Spark on YARN

    1 Spark 的4种运行模式 不管使用寿命模式,Spark 应用程序的代码是不变的,只需要在提交的时候通过 --master参数来指定 Local,开发时使用 Standalone,Spark自带的 ...

  3. Spark学习笔记(7)---Spark SQL学习笔记

    Spark SQL学习笔记 Spark SQL学习笔记设计到很多代码操作,所以就放在github, https://github.com/yangtong123/RoadOfStudySpark/bl ...

  4. 第71课:Spark SQL窗口函数解密与实战学习笔记

    第71课:Spark SQL窗口函数解密与实战学习笔记 本期内容: 1 SparkSQL窗口函数解析 2 SparkSQL窗口函数实战 窗口函数是Spark内置函数中最有价值的函数,因为很多关于分组的 ...

  5. 学习笔记Spark(七)—— Spark SQL应用(2)—— Spark DataFrame基础操作

    二.Spark DataFrame基础操作 2.1.DataFrame DataFrame是一种不可变的分布式数据集,这种数据集被组织成指定的列,类似于关系数据库中的表. 数据集的每一列都带有名称和类 ...

  6. 学习笔记Spark(六)—— Spark SQL应用(1)—— Spark SQL简介、环境配置

    一.Spark SQL简介 1.1.Spark SQL特性 Spark SQL是Spark Core之上的一个组件,它引入了一个称为SchemaRDD的新- 数据抽象,它为结构化和半结构化数据提供支持 ...

  7. 极光笔记丨Spark SQL 在极光的建设实践

    作者:极光高级工程师-蔡祖光 前言 Spark在2018开始在极光大数据平台部署使用,历经多个版本的迭代,逐步成为离线计算的核心引擎.当前在极光大数据平台每天运行的Spark任务有20000+,执行的 ...

  8. pyspark笔记(RDD,DataFrame和Spark SQL)

    https://github.com/QInzhengk/Math-Model-and-Machine-Learning PySpark RDD和DataFrame 1.SparkSession 介绍 ...

  9. 大数据实时计算Spark学习笔记(9)—— Spar SQL(1) 读取 json 文件

    1 Spark SQL 编程方式:(1)SQL;(2) DataFrame API scala> case class Customer(id:Int,name:String,age:Int) ...

最新文章

  1. Java读取文件流用什么对象_使用Java IO流实现对文本文件的读写过程中,通常需要处理下列( )异常。_学小易找答案...
  2. 飚王硬盘盒怎么样_ORICO M.2固态移动硬盘盒众测分享:移动存储也高速
  3. 如何实现线程池的 QueueUserWorkItem 方法的延续?
  4. java返回object的类型_为什么标准java类的clone()返回Object而不是实际的类型
  5. magento 1.7 中文语言包
  6. Puppet的安装部署
  7. R语言系列:自定义function
  8. Git 分支管理最佳实践(转载)
  9. Java-接口第一篇认识Interface
  10. 组态王、力控、MCGS、瑞尔、杰控等国内组态软件一点看法 1
  11. 【@MaC 修改MySQL密码】
  12. 面试通过,背调凉了。。
  13. MyBatisPlus 查询selectOne方法
  14. libxml2.7.8 c++ 解析xml文件 中文转换
  15. iPad如何分屏?iPad分屏详细教程来啦!
  16. 分区表的概念、优点以及类型
  17. 二阶常系数非齐次线性微分方程的通解
  18. Error in nextTick: “TypeError: Cannot read property ‘__ob__‘ of undefined“
  19. 微信小程序-006-投票功能-搜索投票
  20. 月薪20KPython程序员2018年Python学习进阶书籍推荐

热门文章

  1. 输入经纬度城市名调用第三方地图软件自动规划路线导航
  2. 房卡棋牌分析系列之微信登录
  3. ZZULI郑州轻工业大学21级新生赛正式赛
  4. java计算机毕业设计网上商城系统演示录像源码+系统+数据库+lw文档+mybatis+运行部署
  5. Excel进行数据分析
  6. 開運算、閉運算(morphologyEx、MORPH_OPEN、MORPH_CLOSE)
  7. L1-7 qls学习字符串 (20分)
  8. 游戏版署版本心得(一)
  9. Python九宫格输入功能简单实现
  10. 机器人工程的工作与考研之困惑“以学生为中心”