spark sql使用--创建SparkDataFrame

Spark SQL模块

这个模块是Spark中用来处理结构化数据的,提供一个叫SparkDataFrame的东西并且自动解析为分布式SQL查询数据。

在RDD阶段,程序的执行入口对象是: SparkContext

在Spark 2.0后,推出了SparkSession对象,作为Spark编码的统一入口对象

SparkSession对象的作用:

  • 用于SparkSQL编程作为入口对象

  • 用于SparkCore编程,可以通过SparkSession对象中获取到SparkContext

DataFrame

DataFrame和RDD的对比
  • 相同点:DataFrame和RDD都是:弹性的、分布式的、数据集

  • 不同点:DataFrame存储的数据结构限定为:二维表结构化数据;而RDD可以存储的数据则没有任何限制

也就是说,DataFrame 是按照二维表格的形式存储数据;RDD则是存储对象本身

DataFrame的组成

在结构层面:

  • StructType对象描述整个DataFrame的表结构

  • StructField对象描述一个列的信息

在数据层面:

  • Row对象记录一行数据

  • Column对象记录一列数据并包含列的信息(包含StructField)

schema = StructType().\
add("name", StringType(), nullable=True).\
add("age", IntegerType(), nullable=False)

# StructType是由多个StructField组成的
# 通过add方法向StructType中添加StructField
# 一个StructField记录由列名、列类型、列是否运行为空组成

创建SparkDataFrame

几种创建SparkDataFrame的方法,分别是使用RDD来创建、使用python的pandas创建DataFrame、使用List来创建、读取数据文件来创建、通过读取数据库来创建。

1.使用RDD来创建

主要使用RDD的toDF方法

#appName:任务名称
#config:设置一些属性
#master:Spark运行模式
#getOrCreate:创建SparkSession对象

from pyspark.sql import SparkSession

# 构建SparkSession执行环境入口对象
spark = SparkSession.builder.\
    appName("spark_sql").\
    config("spark.sql.shuffle.partitions", "4").\
    master("local[*]").\
    getOrCreate()

# 通过SparkSession可以获SparkContext对象
sc = spark.sparkContext

#定义rdd
rdd = sc.parallelize([("Sam", 28, 88, "M"),
                      ("Flora", 28, 90, "F"),
                      ("Run", 1, 60, None),
                      ("Peter", 55, 100, "M"),
                      ("Mei", 54, 95, "F")])

df = rdd.toDF(["Name", "age", "score", "sex"])

df.show()
df.printSchema()

#结果如下

+-----+---+-----+----+
| Name|age|score| sex|
+-----+---+-----+----+
|  Sam| 28|   88|   M|
|Flora| 28|   90|   F|
|  Run|  1|   60|null|
|Peter| 55|  100|   M|
|  Mei| 54|   95|   F|
+-----+---+-----+----+

root
 |-- Name: string (nullable = true)
 |-- age: long (nullable = true)
 |-- score: long (nullable = true)
 |-- sex: string (nullable = true)

2.使用python的pandas创建DataFrame


from pyspark.sql import SparkSession
import pandas as pd

# 构建SparkSession执行环境入口对象
spark = SparkSession.builder.\
    appName("spark_sql").\
    config("spark.sql.shuffle.partitions", "4").\
    master("local[*]").\
    getOrCreate()
# 通过SparkSession可以获SparkContext对象
sc = spark.sparkContext

# 首先构建pandas的df对象
pdf = pd.DataFrame(
    {
        "id": [1, 2, 3],
        "name": ["aa", "bb", "cc"],
        "age": [11, 12, 13]
    }
)
# 然后创建spark的df对象
df = spark.createDataFrame(pdf)

df.show()
df.printSchema()


#执行结果
+---+----+---+
| id|name|age|
+---+----+---+
|  1|  aa| 11|
|  2|  bb| 12|
|  3|  cc| 13|
+---+----+---+

root
 |-- id: long (nullable = true)
 |-- name: string (nullable = true)
 |-- age: long (nullable = true)

3.使用list来创建


from pyspark.sql import SparkSession


# 构建SparkSession执行环境入口对象
spark = SparkSession.builder.\
    appName("spark_sql").\
    config("spark.sql.shuffle.partitions", "4").\
    master("local[*]").\
    getOrCreate()
# 通过SparkSession可以获SparkContext对象
sc = spark.sparkContext

list_values = [["aa", 28, 88], ["bb", 28, 90], ["cc", 1, 60]]
df = spark.createDataFrame(list_values, ["name", "age", "score"])
df.show()
df.printSchema()

#执行结果如下
+----+---+-----+
|name|age|score|
+----+---+-----+
|  aa| 28|   88|
|  bb| 28|   90|
|  cc|  1|   60|
+----+---+-----+

root
 |-- name: string (nullable = true)
 |-- age: long (nullable = true)
 |-- score: long (nullable = true)

4.读取数据文件来创建


from pyspark.sql import SparkSession


# 构建SparkSession执行环境入口对象
spark = SparkSession.builder.\
    appName("spark_sql").\
    config("spark.sql.shuffle.partitions", "4").\
    master("local[*]").\
    getOrCreate()
# 通过SparkSession可以获SparkContext对象
sc = spark.sparkContext

df = spark.read.format("text")\
    .option("interSchema", "true")\
    .option("delimiter", " ")\
    .schema("name STRING")\
    .load("./word.txt")


df.show()
df.printSchema()

#执行结果如下

+------------------+
|              name|
+------------------+
| hive spark hadoop|
|hadoop spark hbase|
+------------------+

root
 |-- name: string (nullable = true)


#读取json数据:format("json")
json自带schema,直接load即可:
df = spark.read.format("json").load("hdfs://10.245.150.47:8020/user/wuhaoyi/input/sql/people.json")

#读取csv数据:format("csv")
df = spark.read.format("csv").\
option("sep", ";").\ # 列分隔符
option("header", True).\ # 是否有CSV标头
option("encoding", "utf-8").\ # 编码
schema("name STRING, age INT, job STRING").\ # 列名和类型
load("hdfs://10.245.150.47:8020/user/wuhaoyi/input/sql/people.csv")


#读取parquet数据:format("parquet")
parquet自带schema,直接load即可:
df = spark.read.format("parquet").load("hdfs://10.245.150.47:8020/user/wuhaoyi/input/sql/users.parquet")

5.通过读取数据库来创建


from pyspark.sql import SparkSession


# 构建SparkSession执行环境入口对象
spark = SparkSession.builder.\
    appName("spark_sql").\
    config("spark.sql.shuffle.partitions", "4").\
    master("local[*]").\
    getOrCreate()
# 通过SparkSession可以获SparkContext对象
sc = spark.sparkContext

url = "jdbc:mysql://192.168.10.106:3306/test"

df = spark.read.format("jdbc")\
    .option("url", url)\
    .option("dbtable", "test")\
    .option("user", "root")\
    .option("password", "123456")\
    .load()\

df.show()
df.printSchema()


#执行结果如下

+--------------------+-------------+---------------+
|          order_code|serial_number|             ip|
+--------------------+-------------+---------------+
| 4849818240345981248|  123456     |192.168.10.106 |
| 4849818240345981248|  123456     |192.168.10.106 |
+--------------------+-------------+---------------+
only showing top 20 rows

root
 |-- order_code: string (nullable = true)
 |-- serial_number: string (nullable = true)
 |-- ip: string (nullable = true)


###操作数据库需要将数据库驱动添加到java对应目录下否则会报错:java.sql.SQLException: No suitable driver

#####DataFrame 通过JDBC读写数据库

首先需要在anaconda中安装mysql的驱动:

将mysql的驱动包放在anaconda3/envs/pyspark/lib/python3.8/site-packages/pyspark/jars/路径下

mysql-connector-java.jar

或者放在java指定目录下

C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext

![](https://img2023.cnblogs.com/blog/2069550/202310/2069550-20231017160039645-1898787876.png)

DSL(领域特定语言)语法风格

以调用DataFrame特有的API的方式来处理Data

show

功能:展示DataFrame中的数据, 默认展示20条

df.show(参数1, 参数2)
- 参数1: 默认是20, 控制展示多少条
- 参数2: 是否截断列, 默认只输出20个字符的长度, 过长不显示, 要显示的话 应填入 truncate = True

printSchema

功能:打印输出df的schema信息

语法:df.printSchema()

select

功能:选择DataFrame中的指定列

语法:


# select方法的参数支持字符串形式、column形式传入
# 字符串形式
df.select(["id", "subject"]).show()
df.select("id", "subject").show()
# column形式
# 首先获取column对象
id_column = df['id']
subject_column = df['subject'] #从df中根据列名获取
# 然后传入
df.select(id_column, subject_column).show()

filter和where

功能:过滤DataFrame内的数据,返回一个过滤后的DataFrame

(二者是等价的)

语法:

# 字符串形式
df.filter("score < 99").show()
# column形式
df.filter(df['score'] < 99).show()

groupBy

功能:按照指定的列进行数据的分组, 返回值是GroupedData对象

语法:

# 告知spark需要按照哪个列进行分组:
# 字符串形式
df.groupBy("subject").count().show()
# column形式
df.groupBy(df['subject']).count().show()

SQL风格语法

注册DataFrame成为表 语法:

# 注册成临时表
df.createTempView("table") # 注册临时视图(表)
df.createOrReplaceTempView("table2") # 注册或者替换临时视图表
df.createGlobalTempView("table3") # 注册全局临时视图;全局临时视图在使用的时候需要在前面带上global_temp.前缀

全局表和临时表的区别

  • 临时表:只能在当前SparkSession使用;
  • 全局表:可以跨SparkSession使用,在一个程序内的多个SparkSession中均可调用,但查询时需要前缀global_temp

使用sql查询

语法:sparksession.sql(sql语句)

df.createTempView("test2")
spark.sql("select * from test2 limit 5").show()

DataFrame数据写出

语法:df.write.mode().format().option(K,V).save(path)

mode:写出的模式;包括append:追加|overwrite:覆盖|ignore:忽略|error:文件重复则报异常(默认)

format:文件格式,包括text|csv|json|parquet|orc|avro|jdbc

option:属性

save:保存路径

需要注意的是,text只能写出一个单列数据

# 需要将df转换为单列df
df.select(F.concat_ws("---", "user_id", "movie_id", "rank", "ts")).\
        write.\
        mode("overwrite").\
        format("text").\
        save("../data/output/sql/text")

参考文档

https://zhuanlan.zhihu.com/p/395431025
https://juejin.cn/post/7230613183186452536

posted @ 2023-10-17 16:08  whiteY  阅读(294)  评论(0)    收藏  举报