Spark SQL是Apache Spark生态系统中的一个重要组件,它提供了一种高效、简洁的数据查询接口,支持SQL语法和DataFrame API。Spark SQL可以让用户基于结构化和半结构化数据(比如JSON)进行交互式查询,并且可以与Hive集成。
Spark SQL核心包括以下两个主要模块:
-
Catalyst Optimizer:Catalyst 优化器是由 Spark SQL 基于规则推导出来的、能够对逻辑计划进行自动转换和优化的工具。当我们向将 Sql 转为计算可执行代码时,这个工具会应用诸多优化技术并生成更加有效率以及容易执行的物理计划 例如:常量折叠、谓词下移合并等等;
-
Tungsten Execution Engine :Tungsten 执行引擎解决了 JVM 反压机制不足问题 ,采用二进制内存管理(Batch Memory Management)、CPU Cache-aware 策略等多种方式大幅度地提升了spark任务处理性能, 提供了增强版Memory Manager,SerDe,Code generator以及一些新内存使用手段。
同时还有外部插件:
-
对 Hive 的兼容 。Databricks 公司改良后面包括线上服务 Databricks 平台在内很好地实现 Hive 包括Metastore原有 api 大小写不敏感 (主要指列名) 等问题;
-
类 MySQL JDBC/ODBC接口 。RDD 方式连接已经有了,而 Spark SQL 采用了类似于 mysql 的形式提供 jdbc 和 odbc 接口;
Spark的优点
-
可以通过SQL语法来进行数据查询和处理。这使得开发人员能够更加直接地使用SQL的方式对大型及分布式数据做统一处理,简化了代码量和开发难度。
-
SparkSql支持结构化的数据类型,并提供了强类型API(DataFrame API),可以在保证性能不降的情况下避免各种运行时错误。
-
SparkSql具备高可扩展性,可以方便地嵌入到现有Spark生态环境中,如Mllib、图计算等模块,而且还能与Hadoop生态系统无缝集成。这使得开发人员只需掌握一个工具就可以完成多项任务。
-
基于Catalyst优化器引擎的所谓“Query Pipeline”管道设计为Spark用户带来了很大的好处:自动解析SQL转换为物理流程图形式;内置推导机制根据查询规则进行调整逻辑流程从而达到最佳体验效果;增强版Memory Manager,SerDe,Code generator 以及一些新内存使用手段
-
Spark SQL还涉及针对 Hive Metastore 的原表格式映射关系 ,类mysql jdbc/odbc 接口 等特色架构分类 对于大量数仓等场景非常友好.
入门案例
接下来我将为大家写一个简单的SparkSql入门案例。这个示例程序会使用SparkSql从本地文件系统读取数据,并对其进行聚合操作和统计分析。
首先,我们需要准备一份测试数据:假设有如下CSV格式数据:
name,age,score
Tom,18,97
Jack,20,86
Lucy,19,91
Mary,21,78
Bob,,85
然后在代码中通过以下步骤实现上述需求:
- 首先创建SparkSession对象
import org.apache.spark.sql.SparkSession
val spark = SparkSession.builder().appName("SimpleApp").config("spark.master", "local[*]").getOrCreate()
- 读取csv文件内容并转换成DataFrame
val df = spark.read.format("csv")
.option("header","true")
.option("inferSchema","true")//自动推断列类型,相当于执行了df.withColumn("", $"col".cast)
.load("/path/to/csvfile")
- 统计每个人年龄、平均分数以及最高分数等信息,并按照平均分排序输出结果
df.groupBy($"age" as "年龄") // 按照 age 分组
.agg(avg($"score") as "平均值",max($"score") as "最高值" ) // 计算统计指标
.orderBy(desc("平均值")) // 结果按照 avgScore 排序
.show() // 显示结果
完整代码如下:
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
object SimpleApp {
def main(args: Array[String]) {
val spark = SparkSession.builder()
.appName("SimpleApp")
.config("spark.master", "local[*]")
.getOrCreate()
val df = spark.read.format("csv")
.option("header","true")
.option("inferSchema","true")//自动推断列类型,相当于执行了df.withColumn("", $"col".cast)
.load("/path/to/csvfile")
df.groupBy($"age" as "年龄") // 按照 age 分组
.agg(avg($"score") as "平均值",max($"score") as "最高值" ) // 计算统计指标
.orderBy(desc("平均值")) // 结果按照 avgScore 排序
.show()
spark.stop()
}
}
请注意替换代码中的数据源路径和保存路径。运行该程序后,SparkSql会对CSV文件进行解析,并输出每个年龄段学生的平均分数以及最高分数等信息(按照平均分排序)。