持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第10天,点击查看活动详情
Spark SQL的简介
Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象结构叫做DataFrame的数据模型(即带有Schema信息的RDD),Spark SQL作为分布式SQL查询引擎,让用户可以通过SQL、DataFrames API和Datasets API三种方式实现对结构化数据的处理。
Spark SQL主要提供了以下三个功能:
Spark SQL可从各种结构化数据源(JSON、Hive)中读取数据,进行数据分析。 Spark SQL包含行业标准的JDBC和ODBC连接方式,因此它不局限于在Spark程序内使用SQL语句进行查询。 Spark SQL可以无缝地将SQL查询与Spark程序进行结合,它能够将结构化数据作为Spark中的分布式数据集(RDD)进行查询。
Spark SQL工作流程:
DataFrame概述:
DataFrame简介:
Spark SQL使用的数据抽象并非是RDD,而是DataFrame。
在Spark 1.3.0版本之前,DataFrame被称为SchemaRDD。
DataFrame使Spark具备处理大规模结构化数据的能力。
在Spark中,DataFrame是一种以RDD为基础的分布式数据集。
DataFrame的结构类似传统数据库的二维表格,可以从很多数据源中创建,如结构化文件、外部数据库、Hive表等数据源。
DataFrame的特点:
支持KB级到PB级的数据处理。
支持读取多种存储系统的数据及支持多种数据格式。
提供了Python、Java、Scala、R等多种语言API。
能够无缝集成Spark上的大数据处理工具。
通过Spark SQL Catalyst优化器可以进行高效的代码生成与优化
创建DataFrame的几种方式:
(1)从结构化数据文件(txt、csv、json)创建DataFrame
(2)已存在的RDD调用toDF()方法转换得到DataFrame
(3)从外部数据库(MySQL、Oracle)创建DataFrame
(4)从Hive中的表创建DataFrame
1.通过读取文件直接创建DataFrame
读取*.txt文件
scala > val personDF = spark.read.text("/sparkdata/person.txt")
personDF: org.apache.spark.sql.DataFrame = [value: String]
scala > personDF.printSchema()
root
|-- value: String (Nullable = true)
scala> personDF.show()
读取*.csv文件
scala> val df_csv=spark.read.csv("/sparkdata/person.csv")
df_csv: org.apache.spark.sql.DataFrame = [_c0: string]
scala> df_csv.show( )
右图的结果存在两个问题:
- 列标题被当成数据了
- 因为csv文件默认的分隔符是逗号,所以,分号隔开的数据被看成一行了。
解决方法:
scala> val df_csv=spark.read.option("header","true").option("sep",";").csv("/sparkdata/person.csv")
df_csv: org.apache.spark.sql.DataFrame = [id: string, name: string ... 1 more field]
scala> df_csv.show( )
读取*.json文件
scala> val df_json=spark.read.json("/sparkdata/person.json")
df_json: org.apache.spark.sql.DataFrame = [age: bigint, name: string]
scala> df_json.show()
2.RDD直接转换为DataFrame
方法1
利用反射机制推断RDD模式,使用这种方式首先需要定义一个case class,
因为只有case class才能被Spark隐式地转换为DataFrame。
步骤如下:
(1)先定义一个样例类Person
(2)读取文件的方式创建一个RDD,并且以空格分隔一行文本
(3)调用map算子将数组中的每个元素映射为Person类中的每个属性
(4)调用toDF()方法将RDD转换为DataFrame
scala > case class Person(id:Int,name:String,age:Int)
defined class Person
scala > val lineRDD = sc.textFile("/sparkdata/person.txt").map(_.split(" "))
lineRDD: org.apache.spark.rdd.RDD[Array[String]] = MapPartitionsRDD[6] at map at <console>:24
scala > val personRDD = lineRDD.map(x => Person(x(0).toInt, x(1), x(2).toInt))
personRDD: org.apache.spark.rdd.RDD[Person] = MapPartitionsRDD[7] at map at <console>:27
scala > val personDF = personRDD.toDF()
personDF: org.apache.spark.sql.DataFrame = [id: int, name: string ... 1 more field]
方法2
步骤如下:
(1)从原始RDD创建一个元素为Row类型的RDD
(2)用StructType创建一个和RDD中Row的结构相匹配的Schema
(3)通过SparkSession提供的createDataFrame方法将Schema应用到RDD上
3.从外部数据库创建DataFrame
Spark SQL可以从外部数据库(比如MySQL、Oracle等数据库)中创建DataFrame。使用这种方式创建DataFrame需要通过JDBC连接或ODBC连接的方式访问数据库。
首先,准备所需要环境
准备环境:
(1)将MySQL驱动包复制到Spark安装路径下的jars目录下,命令如下:
[root@node01 ~]# cp /opt/apps/mysql-connector-java-5.1.49.jar /opt/apps/spark/jars
(2)把Spark SQL连接到一个部署好的Hive时,必须把hive-site.xml配置文件复制到Spark的配置文件目录中,这里采用软件连接方式,命令如下:
[root@node01 ~]# ln -s /opt/apps/hive/conf/hive-site.xml /opt/apps/spark/conf/hive-site.xml
(3)在/opt/apps/hive/conf/hive-site.xml里关闭元数据验证机制,否则会出现org.apache.hadoop.hive.metastore.api.MetaException: Hive Schema version 1.2.0 does not match metastore's schema version 2.3.0 Metastore is not upgraded等错误
(3)将hive-site.xml文件中属性hive.metastore.schema.verification的属性值由true修改为false。
(4)启动mysql服务(已设置了开机自启动)
systemctl start mysqld
(5)修改Spark日志级别。
[root@node01 ~]# cd /opt/apps/spark/conf
[root@node01 conf]# cp log4j.properties.template log4j.proerties
[root@node01 conf]# vim log4j.proerties
输入命令 ?log4j.rootCategory 快速查找关键信息,将log4j.rootCategory 的值由INFO修改为WARN
4.从Hive中的表创建DataFrame
方法1:通过SQL查询语句 spark.sql()
方法2:table方法 spark.read.table(tablename)