spark-sql总结
文章目录
1、Spark SQL 概述
Spark SQL概念
- Spark SQL is Apache Spark’s module for working with structured data.
- 它是spark中用于处理结构化数据的一个模块
Spark SQL历史
- Hive是目前大数据领域,事实上的数据仓库标准。
- Shark:shark底层使用spark的基于内存的计算模型,从而让性能比Hive提升了数倍到上百倍。
- 底层很多东西还是依赖于Hive,修改了内存管理、物理计划、执行三个模块
- 2014年6月1日的时候,Spark宣布了不再开发Shark,全面转向Spark SQL的开发
Spark SQL优势
- Write Less Code
- Performance
python操作RDD,转换为可执行代码,运行在java虚拟机,涉及两个不同语言引擎之间的切换,进行进程间 通信很耗费性能。
DataFrame
- 是RDD为基础的分布式数据集,类似于传统关系型数据库的二维表,dataframe记录了对应列的名称和类型
- dataFrame引入schema和off-heap(使用操作系统层面上的内存)
- 1、解决了RDD的缺点
- 序列化和反序列化开销大
- 频繁的创建和销毁对象造成大量的GC
- 2、丢失了RDD的优点
- RDD编译时进行类型检查
- RDD具有面向对象编程的特性
用scala/python编写的RDD比Spark SQL编写转换的RDD慢,涉及到执行计划
- CatalystOptimizer:Catalyst优化器
- ProjectTungsten:钨丝计划,为了提高RDD的效率而制定的计划
- Code gen:代码生成器
直接编写RDD也可以自实现优化代码,但是远不及SparkSQL前面的优化操作后转换的RDD效率高,快1倍左右
优化引擎:类似mysql等关系型数据库基于成本的优化器
首先执行逻辑执行计划,然后转换为物理执行计划(选择成本最小的),通过Code Generation最终生成为RDD
-
Language-independent API
用任何语言编写生成的RDD都一样,而使用spark-core编写的RDD,不同的语言生成不同的RDD
-
Schema
结构化数据,可以直接看出数据的详情
在RDD中无法看出,解释性不强,无法告诉引擎信息,没法详细优化。
**为什么要学习sparksql **
sparksql特性
- 1、易整合
- 2、统一的数据源访问
- 3、兼容hive
- 4、提供了标准的数据库连接(jdbc/odbc)
2、DataFrame
2.1 介绍
在Spark语义中,DataFrame是一个分布式的行集合,可以想象为一个关系型数据库的表,或者一个带有列名的Excel表格。它和RDD一样,有这样一些特点:
- Immuatable:一旦RDD、DataFrame被创建,就不能更改,只能通过transformation生成新的RDD、DataFrame
- Lazy Evaluations:只有action才会触发Transformation的执行
- Distributed:DataFrame和RDD一样都是分布式的
- dataframe和dataset统一,dataframe只是dataset[ROW]的类型别名。由于Python是弱类型语言,只能使用DataFrame
DataFrame vs RDD
- RDD:分布式的对象的集合,Spark并不知道对象的详细模式信息
- DataFrame:分布式的Row对象的集合,其提供了由列组成的详细模式信息,使得Spark SQL可以进行某些形式的执行优化。
- DataFrame和普通的RDD的逻辑框架区别如下所示:
-
左侧的RDD Spark框架本身不了解 Person类的内部结构。
-
右侧的DataFrame提供了详细的结构信息(schema——每列的名称,类型)
-
DataFrame还配套了新的操作数据的方法,DataFrame API(如df.select())和SQL(select id, name from xx_table where …)。
-
DataFrame还引入了off-heap,意味着JVM堆以外的内存, 这些内存直接受操作系统管理(而不是JVM)。
-
RDD是分布式的Java对象的集合。DataFrame是分布式的Row对象的集合。DataFrame除了提供了比RDD更丰富的算子以外,更重要的特点是提升执行效率、减少数据读取以及执行计划的优化。
-
DataFrame的抽象后,我们处理数据更加简单了,甚至可以用SQL来处理数据了
-
通过DataFrame API或SQL处理数据,会自动经过Spark 优化器(Catalyst)的优化,即使你写的程序或SQL不仅高效,也可以运行的很快。
-
DataFrame相当于是一个带着schema的RDD
Pandas DataFrame vs Spark DataFrame
- Cluster Parallel:集群并行执行
- Lazy Evaluations: 只有action才会触发Transformation的执行
- Immutable:不可更改
- Pandas rich API:比Spark SQL api丰富
2.2 创建DataFrame
1,创建dataFrame的步骤
调用方法例如:spark.read.xxx方法
2,其他方式创建dataframe
-
createDataFrame:pandas dataframe、list、RDD
-
数据源:RDD、csv、json、parquet、orc、jdbc
jsonDF = spark.read.json("xxx.json") jsonDF = spark.read.format('json').load('xxx.json') parquetDF = spark.read.parquet("xxx.parquet") jdbcDF = spark.read.format("jdbc").option("url","jdbc:mysql://localhost:3306/db_name").option("dbtable","table_name").option("user","xxx").option("password","xxx").load()
-
Transformation:延迟性操作
-
action:立即操作
2.3 DataFrame API实现
基于RDD创建
import os
# spark配置信息
import sys
sys.path.append('/toutiao_project/py4j-0.10.7-src.zip')
sys.path.append('/toutiao_project/pyspark.zip')
# 配置spark driver和pyspark运行时,所使用的python解释器路径
SPARK_HOME = '/app/spark-2.4.7'
JAVA_HOME = '/app/jdk1.8.0_271'
# 当存在多个版本时,不指定很可能会导致出错
PYSPARK_PYTHON = '/root/Envs/aipy36/bin/python3'
os.environ['SPARK_HOME'] = SPARK_HOME
os.environ['JAVA_HOME'] = JAVA_HOME
os.environ['PYSPARK_PYTHON'] = PYSPARK_PYTHON
os.environ['PYSPARK_DIRVER_PYTHON'] = PYSPARK_PYTHON
from pyspark import SparkConf
from pyspark.sql import SparkSession
SPARK_APP_NAME = "dataframetest"
SPARK_URL = "spark://192.168.31.137:7077"
conf = SparkConf() # 创建spark config对象
config = (
("spark.app.name", SPARK_APP_NAME), # 设置启动的spark的app名称,没有提供,将随机产生一个名称
("spark.executor.memory", "2g"), # 设置该app启动时占用的内存用量,默认1g
("spark.master", SPARK_URL), # spark master的地址
("spark.executor.cores", "4"), # 设置spark executor使用的CPU核心数
# 以下三项配置,可以控制执行器数量
# ("spark.dynamicAllocation.enabled", True),
# ("spark.dynamicAllocation.initialExecutors", 1), # 1个执行器
# ("spark.shuffle.service.enabled", True)
# ('spark.sql.pivotMaxValues', '99999'), # 当需要pivot DF,且值很多时,需要修改,默认是10000
)
# 查看更详细配置及说明:https://spark.apache.org/docs/latest/configuration.html
conf.setAll(config)
# 利用config对象,创建spark session
spark = SparkSession.builder.config(conf=conf).getOrCreate()
sc = spark.sparkContext
# spark.conf.set("spark.sql.shuffle.partitions", 6)
# ================直接创建==========================
l = [('Ankit',25),('Jalfaizy',22),('saurabh',20),('Bala',26)]
rdd = sc.parallelize(l)
#为数据添加列名
people = rdd.map(lambda x: Row(name=x[0], age=int(x[1])))
#通过sparkSession创建DataFrame
schemaPeople = spark.createDataFrame(people)
schemaPeople.show()
从csv中读取数据
#!hadoop fs -put ../data/iris.csv /user/root
# ==================从csv读取======================
#加载csv类型的数据并转换为DataFrame
df = spark.read.format("csv"). \
option("header", "true") \
.load(