Spark开发--Spark SQL--数据源(十六)

一、数据源

  Spark SQL的默认数据源格式为parquet格式。数据源为Parquet文件时,SparkSQL 可以方便地进行读取,甚至可以直接在Parquet 文件上执行查询操作。修改配置项spark.sqlsources.default,可以修改默认数据源格式。
  当数据源不是parquet格式文件时,需要手动指定数据源的格式。
  数据源格式需指定全名(如org.apachesparksl.parquet)
  如果数据源为内置格式,则只需指定简称(json, parquet,jdbc, ore, libsvm, csv, text )即可。

1. Parquet

Parquet存储的优势:
(I)可以跳过不符合条件的数据,只读取需要的数据,降低IO数据量。
(2)压缩编码可以降低磁盘存储空间。由于同一列的数据类型是一样的, 可以使用更高效的压缩编码
(例如Run Length Encoding和Delta Encoding)进一步节约存储空间。
(3)只读取需要的列,支持向量运算,能够获取更好的扫描性能。

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

1) Parquet格式写入

scala> import spark.implicits._
import spark.implicits._
// 从内存中创建一个DataFrame
scala> val df = Seq(("Ming", 20, 15552211521L), ("hong", 19, 13287994007L), ("zhi", 21, 15552211523L)).toDF("name", "age", "phone")
df: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> df.show()
+----+---+-----------+
|name|age|      phone|
+----+---+-----------+
|Ming| 20|15552211521|
|hong| 19|13287994007|
| zhi| 21|15552211523|
+----+---+-----------+
// 以Parquet的格式写入
scala> df.write.format("parquet").save("file:///root/parquet")

option支持参数

名称 默认值 描述
compression null 保存到文件时使用的压缩编解码器,如(none,bzip2,gzip,lz4,snappy和deflate),不区分大小写。

2) Parquet格式读取

// 读取Parquet
scala> val parquetDF = spark.read.format("parquet").load("file:///root/parquet")
parquetDF: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> parquetDF.printSchema()
root
 |-- name: string (nullable = true)
 |-- age: integer (nullable = true)
 |-- phone: long (nullable = true)

option参数

名称 默认值 描述
mergeSchema false 如果为true,则将文件作为单行读取,而不是按“\ n”拆分
// 读取数据
scala> val df = spark.read.load("file:///usr/local/spark-2.4.4-bin-hadoop2.7/examples/src/main/resources/users.parquet") 
df: org.apache.spark.sql.DataFrame = [name: string, favorite_color: string ... 1 more field]
// 另存为文件namesAndFavColors.parquet
scala> df.select("name", "favorite_color").write.save("file:///root/namesAndFavColors.parquet")
# 查看结果
root@master:~# ls /root/name*
part-00000-3d4c5b0f-67d7-473e-bf85-3b20260db66b-c000.snappy.parquet  _SUCCESS

2. JSON

  Spark SQL可处理的数据源包括简洁高效,常用于网络传输的JSON格式数据集。
  Spark SQL可以自动推断JSON数据集的结构信息(Schema),并将其作为DataSel[Row]即DataFrame对象返回。通过将Dataset [String]其中String对象是典型的JSON格式字符串)或表示JSON文件存储位置的路径字符中传入SparkSession.readjson ()方法中来完成此转换。
需要注意的是,作为JSON文件提供的文件不是典型的JSON文件。每行必须包含一 个单独的,独立的有效的JSON对象。

1)json格式写入


scala> import spark.implicits._
import spark.implicits._

scala> val df = Seq(("Ming", 20, 15552211521L), ("hong", 19, 13287994007L), ("zhi", 21, 15552211523L)).toDF("name", "age", "phone")
df: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> df.show()
+----+---+-----------+
|name|age|      phone|
+----+---+-----------+
|Ming| 20|15552211521|
|hong| 19|13287994007|
| zhi| 21|15552211523|
+----+---+-----------+

//以json格式写入文件
df.write.format("json").save("file:///root/json")

// 结果查看
root@master:~# ls json
part-00000-cc4acdd4-53dd-4b04-a203-f1166e426be5-c000.json  _SUCCESS
root@master:~# cat json/part-00000-cc4acdd4-53dd-4b04-a203-f1166e426be5-c000.json 
{"name":"Ming","age":20,"phone":15552211521}
{"name":"hong","age":19,"phone":13287994007}
{"name":"zhi","age":21,"phone":15552211523}

// 指定SaveMode
scala> df.write.format("json").mode("errorifexists").save("file:///data/json")

常见的SaveMode:

SaveMode 描述
errorifexists 默认,如果文件存在报错
append 将DataFrame保存到数据源时,如果数据/表已存在,则DataFrame的内容应附加到现有数据。
overwrite 覆盖模式意味着在将DataFrame保存到数据源时,如果数据/表已经存在,则预期现有数据将被DataFrame的内容覆盖。
ignore 忽略模式意味着在将DataFrame保存到数据源时,如果数据已存在,则预期保存操作不会保存DataFrame的内容并且不会更改现有数据。这与CREATE TABLE IF NOT EXISTSSQL中的类似。

在写json时,我们也可以通过option传入特定的参数,支持参数如下所示:

名称 默认值 描述
compression null 保存到文件时使用的压缩编解码器,如(none,bzip2,gzip,lz4,*snappy和deflate),不区分大小写。
dateFormat yyyy-MM-dd 设置指示日期格式的字符串。 自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于日期类型。
timestampFormat yyyy-MM-dd’T’HH:mm:ss.SSSXXX 设置表示时间戳格式的字符串。自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于时间戳类型
encoding 指定已保存的json 文件的编码(charset)。如果未设置,将使用UTF-8字符集。
lineSep \n 指定行分隔符

2) json格式读取

// 读取json数据源,json为存放json文件的目录名
scala>  val jsonDF = spark.read.format("json").load("file:///root/json")
jsonDF: org.apache.spark.sql.DataFrame = [age: bigint, name: string ... 1 more field]

scala>  jsonDF.show()
+---+----+-----------+
|age|name|      phone|
+---+----+-----------+
| 20|Ming|15552211521|
| 19|hong|13287994007|
| 21| zhi|15552211523|
+---+----+-----------+

读取json支持的参数:

名称 默认值 描述
primitivesAsString false 将所有原始值推断为String类型
prefersDecimal false 将所有浮点值推断为十进制类型。如果值不适合十进制,那么它将它们推断为双精度数。
allowComments false 忽略JSON记录中的Java / C ++样式注释
allowUnquotedFieldNames false 允许不带引号的JSON字段名称
allowSingleQuotes true 除了双引号外允许使用单引号
allowNumericLeadingZeros false 允许数字之前有零,(e.g. 00012)
allowBackslashEscapingAnyCharacter false 允许使用反斜杠引用机制接受所有字符的引用
allowUnquotedControlChars false 允许JSON字符串包含不带引号的控制字符(值小于32的ASCII字符,包括制表符和换行符)或不包含。
mode PERMISSIVE 允许在解析过程中处理损坏记录的模式。共有三种模式:
PERMISSIVE:当它遇到损坏的记录时,将格式错误的字符串放入由columnNameOfCorruptRecord配置的字段中,并将其他字段设置为“null”。为了保持损坏的记录,用户可以在用户定义的模式中设置名为columnNameOfCorruptRecord的字符串类型字段。如果架构没有字段,它在解析过程中丢弃损坏的记录。在推断模式时,它会在输出模式中隐式添加columnNameOfCorruptRecord字段。
DROPMALFORMED:忽略整个损坏的记录
FAILFAST:当遇到损坏记录时抛出异常
columnNameOfCorruptRecord spark.sql.columnNameOfCorruptRecord中指定的值 允许重命名具有由’PERMISSIVE模式创建的格式错误的字符串的新字段。这会覆盖spark.sql.columnNameOfCorruptRecord`
dateFormat yyyy-MM-dd 设置指示日期格式的字符串。 自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于日期类型。
timestampFormat yyyy-MM-dd’T’HH:mm:ss.SSSXXX 设置表示时间戳格式的字符串。自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于时间戳类型。
multiLine false 解析一个记录,每个文件可能跨越多行
encoding 允许强制为JSON文件设置标准基本或扩展编码之一。例如UTF-16BE,UTF-32LE。如果未指定encoding 并且multiLine设置为true,则会自动检测到它。
lineSep \r, \r\n and \n 行分隔符
samplingRatio 1.0 定义用于模式推断的输入JSON对象的分数

3. CSV文件

1) csv格式写入

scala> import spark.implicits._
import spark.implicits._

scala> val df = Seq(("Ming", 20, 15552211521L), ("hong", 19, 13287994007L), ("zhi", 21, 15552211523L)).toDF("name", "age", "phone")
df: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> df.show()
+----+---+-----------+
|name|age|      phone|
+----+---+-----------+
|Ming| 20|15552211521|
|hong| 19|13287994007|
| zhi| 21|15552211523|
+----+---+-----------+

 // 以csv格式写入文件
scala> df.write.format("csv").mode("overwrite").save("file:///root/csv")

// 输出结果
root@master:~# ls csv*
part-00000-532cf409-32c8-4a3e-8875-0fced5339d50-c000.csv  _SUCCESS
root@master:~# cat csv/part-00000-532cf409-32c8-4a3e-8875-0fced5339d50-c000.csv 
Ming,20,15552211521
hong,19,13287994007
zhi,21,15552211523

option参数列表:

名称 默认值 描述
sep , 列分隔符
quote " 设置用于转义引用值的单个字符,其中分隔符可以是值的一部分。如果设置了空字符串,则使用u0000 (空字符)
escape \ 设置一个用于在已引用的值内转义引号的单个字符。
charToEscapeQuoteEscaping escape or \0 设置一个单独的字符,用于转义引号字符的转义。当转义和引号字符不同时,默认值为转义字符,否则为“\ 0”
escapeQuotes true 一个标志,指示包含引号的值是否应始终用引号括起来。默认是转义包含引号字符的所有值。
quoteAll false 一个标志,指示是否所有值都应始终用引号括起来。默认是仅转义包含引号字符的值。
header false 将第一行写为列的名称
nullValue 空字符串 设置空值的字符串表示形式。
compression null 保存到文件时使用的压缩编解码器,如(none,bzip2,gzip,lz4,snappy和deflate),不区分大小写。
dateFormat yyyy-MM-dd 设置指示日期格式的字符串。 自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于日期类型。
timestampFormat yyyy-MM-dd’T’HH:mm:ss.SSSXXX 设置表示时间戳格式的字符串。自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于时间戳类型。
ignoreLeadingWhiteSpace true 一个标志,指示是否应该跳过正在写入的值的头部空格。
ignoreTrailingWhiteSpace true 一个标志,指示是否应该跳过正在写入的值的尾部空格。

2) csv格式读取

scala> val csvDF = spark.read.format("csv").options(Map("sep"->",","inferSchema"->"true","header"->"true")).load("file:///root/csv")
csvDF: org.apache.spark.sql.DataFrame = [Ming: string, 20: int ... 1 more field]

scala> csvDF.show()
+----+---+-----------+
|Ming| 20|15552211521|
+----+---+-----------+
|hong| 19|13287994007|
| zhi| 21|15552211523|
+----+---+-----------+

option参数列表:

名称 默认值 描述
sep , 列分隔符
encoding UTF-8 编码格式
quote " 设置用于转义引用值的单个字符,其中分隔符可以是值的一部分。如果设置了空字符串,则使用u0000 (空字符)
escape \ 设置一个用于在已引用的值内转义引号的单个字符。
comment empty string 设置一个用于跳过以此字符开头的行的单个字符。默认情况下,它被禁用。
header false 将第一行写为列的名称
enforceSchema true 如果将其设置为“true”,则将强制将指定或推断的模式应用于数据源文件,并忽略CSV文件中的标头。 如果该选项设置为“false”,则在header选项设置为“true”的情况下,将针对CSV文件中的所有标头验证模式。模式中的字段名称和CSV标题中的列名称通过考虑spark.sql.caseSensitive的位置进行检查。虽然默认值为true,但建议禁用 enforceSchema`选项以避免不正确的结果。
inferSchema true 从数据中自动推断输入模式。 需要对数据进行一次额外的传递。
samplingRatio 1.0 定义用于模式推断的行的分数。
dateFormat yyyy-MM-dd 设置指示日期格式的字符串。 自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于日期类型。
timestampFormat yyyy-MM-dd’T’HH:mm:ss.SSSXXX 设置表示时间戳格式的字符串。自定义日期格式遵循java.text.SimpleDateFormat中的格式。这适用于时间戳类型。
ignoreLeadingWhiteSpace false 忽略开头是空格的值
ignoreTrailingWhiteSpace false 忽略结尾是空格的值
nullValue empty string 设置空值的字符串表示形式。从*2.0.1开始,这适用于所有支持的类型,包括字符串类型。
nanValue NaN 设置非数字值的字符串表示形式。
positiveInf Inf 设置正无穷大值的字符串表示形式
negativeInf -Inf 设置负无穷大值的字符串表示形式
maxColumns 20480 定义记录可以有多少列的硬限制。
maxCharsPerColumn -1 定义允许读取的任何给定值的最大字符数。默认情况下,它为-1表示无限长度
mode 允许在解析过程中处理损坏记录的模式。共有三种模式:
PERMISSIVE:当它遇到损坏的记录时,将格式错误的字符串放入由columnNameOfCorruptRecord配置的字段中,并将其他字段设置为“null”。为了保持损坏的记录,用户可以在用户定义的模式中设置名为columnNameOfCorruptRecord的字符串类型字段。如果架构没有字段,它在解析过程中丢弃损坏的记录。在推断模式时,它会在输出模式中隐式添加columnNameOfCorruptRecord字段。
DROPMALFORMED:忽略整个损坏的记录
FAILFAST:当遇到损坏记录时抛出异常
columnNameOfCorruptRecord spark.sql.columnNameOfCorruptRecord中指定的值 允许重命名具有由’PERMISSIVE模式创建的格式错误的字符串的新字段。这会覆盖spark.sql.columnNameOfCorruptRecord`
multiLine false 解析一条记录,可能跨越多行。

4. Text文件

1) Text格式写入

scala> import spark.implicits._
import spark.implicits._

scala> val df = Seq(("Ming", 20, 15552211521L), ("hong", 19, 13287994007L), ("zhi", 21, 15552211523L)).toDF("name", "age", "phone")
df: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> df.show()
+----+---+-----------+
|name|age|      phone|
+----+---+-----------+
|Ming| 20|15552211521|
|hong| 19|13287994007|
| zhi| 21|15552211523|
+----+---+-----------+

 // 以text格式写入文件
scala>  val textDF = df.map(_.toSeq.foldLeft("")(_+","+_).substring(1))
textDF: org.apache.spark.sql.Dataset[String] = [value: string]

scala>  textDF.write.format("text").mode("overwrite").save("file:///root/text")

// 查看结果
root@master:~# cat /root/text/part-00000-7ab8f2a4-5e14-46bf-83a0-ce13af18427e-c000.txt 
Ming,20,15552211521
hong,19,13287994007
zhi,21,15552211523

写入text格式时,要求我们的DataFrame只有一列,否则会报错误。

option参数:

名称 默认值 描述
compression null 保存到文件时使用的压缩编解码器,如(none,bzip2,gzip,lz4,snappy和deflate),不区分大小写。
lineSep \r, \r\n and \n 行分隔符

2) Text格式读取

// 读取text文件
scala> val text = spark.read.format("text").load("file:///root/text")
text: org.apache.spark.sql.DataFrame = [value: string]

scala> text.show()
+-------------------+
|              value|
+-------------------+
|Ming,20,15552211521|
|hong,19,13287994007|
| zhi,21,15552211523|
+-------------------+

// 转为DataFrame
// lazy 懒加载就是我们在使用的时候 才会去加载,声明的时候不加载
scala> lazy val first = textDF.first()
first: String = 

scala> val numAttrs = first.split(",").length
numAttrs: Int = 3

scala> import org.apache.spark.sql.functions._
import org.apache.spark.sql.functions._

scala> var newDF = textDF.withColumn("splitCols", split($"value", ","))
newDF: org.apache.spark.sql.DataFrame = [value: string, splitCols: array]
// 0.until 返回一个不包含区间上线的数组
scala> 0.until(numAttrs).foreach(x => {
     |   newDF = newDF.withColumn("col" + "_" + x, $"splitCols".getItem(x))
     | })

scala> newDF.show()
+-------------------+--------------------+-----+-----+-----------+
|              value|           splitCols|col_0|col_1|      col_2|
+-------------------+--------------------+-----+-----+-----------+
|Ming,20,15552211521|[Ming, 20, 155522...| Ming|   20|15552211521|
|hong,19,13287994007|[hong, 19, 132879...| hong|   19|13287994007|
| zhi,21,15552211523|[zhi, 21, 1555221...|  zhi|   21|15552211523|
+-------------------+--------------------+-----+-----+-----------+

Spark SQL 读取text文件,只有一列,这是我们可以通过进一步的处理,转化为以“,”分割的多列DataFrame

option参数

名称 默认值 描述
wholetext false 如果为true,则将文件作为单行读取,而不是按“\ n”拆分
lineSep \r, \r\n and \n 行分隔符

附:

scala> val b= 0.until(10);
b: scala.collection.immutable.Range = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

5. JDBC数据源

创建数据库

1) JDBC数据源写入

scala> import spark.implicits._
import spark.implicits._
// 从内存中创建一个DataFram
scala> val df = Seq(("Ming", 20, 15552211521L), ("hong", 19, 13287994007L), ("zhi", 21, 15552211523L)).toDF("name", "age", "phone")
df: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> df.show()
+----+---+-----------+
|name|age|      phone|
+----+---+-----------+
|Ming| 20|15552211521|
|hong| 19|13287994007|
| zhi| 21|15552211523|
+----+---+-----------+
// 导入依赖包
scala> import java.util.Properties
import java.util.Properties

scala> val connectionProperties = new Properties()
connectionProperties: java.util.Properties = {}
// 设置数据库连接属性
scala>  connectionProperties.put("user", "root")
res1: Object = null

scala>  connectionProperties.put("password", "1234")
res2: Object = null

scala> connectionProperties.put("driver", "com.mysql.jdbc.Driver")
res3: Object = null

// 写入数据库数据
scala> df.write.jdbc("jdbc:mysql://localhost:3306/sparkdata?useSSL=false&characterEncoding=utf-8","spark_people",connectionProperties)
      
写入结果

支持参数:

名称 默认值 描述
url jdbc:subprotocol:subname形式的JDBC数据库url
table 外部数据库中表的名称。
connectionProperties JDBC数据库连接参数,任意字符串标记/值的列表。通常至少应包括“用户”和“密码”属性。 “batchsize”可用于控制每个插入的行数。 “isolationLevel”可以是“NONE”,“READ_COMMITTED”,“READ_UNCOMMITTED”,“REPEATABLE_READ”,或“SERIALIZABLE”之一,对应于JDBC的Connection对象定义的标准事务*隔离级别,默认值为“READ_UNCOMMITTED” 。

3) JDBC数据源读取

// 导入依赖包
scala> import java.util.Properties
import java.util.Properties

scala> val connectionProperties = new Properties()
connectionProperties: java.util.Properties = {}
// 设置数据库连接属性
scala>  connectionProperties.put("user", "root")
res1: Object = null

scala>  connectionProperties.put("password", "1234")
res2: Object = null

scala> connectionProperties.put("driver", "com.mysql.jdbc.Driver")
res3: Object = null
scala> val mysqlDF = spark.read.jdbc("jdbc:mysql://localhost:3306/sparkdata?useSSL=false&characterEncoding=utf-8","spark_people",connectionProperties)
mysqlDF: org.apache.spark.sql.DataFrame = [name: string, age: int ... 1 more field]

scala> mysqlDF.show()
+----+---+-----------+
|name|age|      phone|
+----+---+-----------+
|Ming| 20|15552211521|
|hong| 19|13287994007|
| zhi| 21|15552211523|
+----+---+-----------+

参数列表:

名称 默认值 描述
url jdbc:subprotocol:subname形式的JDBC数据库url
table 表名
columnName 将用于分区的整数类型列的名称。
lowerBound columnName的最小值用于决定分区步幅。
upperBound columnName的最大值用于决定分区步幅。
numPartitions 分区数量。这与lowerBound(包含),upperBound(不包括)一起形成分区,用于生成WHERE 子句表达式,用于均匀地分割列columnName。当*输入小于1时,数字设置为1。
connectionProperties JDBC数据库连接参数,任意字符串标记/值的列表。通常至少应包括“用户”和“密码”属性。 “batchsize”可用于控制每个插入的行数。 “isolationLevel”可以是“NONE”,“READ_COMMITTED”,“READ_UNCOMMITTED”,“REPEATABLE_READ”,或“SERIALIZABLE”之一,对应于JDBC的Connection对象定义的标准事务*隔离级别,默认值为“READ_UNCOMMITTED” 。

6.Hive数据源

  Spark SQL支持对Hive中存储的数据进行读写。操作Hive中的数据时,必须创建HiveContext,而不是SQLContext。
  HiveContext继承自SQLContext,但是增加了在Hive元数据库中查找表,以及用HiveQL语法编写SQL的功能。除了sql()方法,HiveContext还提供了hql()方法,从而用Hive语法来编译sql。
  使用HiveContext,可以执行Hive的大部分功能,包括创建表、往表里导入数据以及用SQL语句查询表中的数据。查询出来的数据是一个Row数组。

1) 配置

  • 普通配置
    hive-site.xml拷贝到spark/conf目录下,将mysql connector拷贝到spark/jars目录下:
root@master:~# cp /usr/local/apache-hive-2.3.6-bin/conf/hive-site.xml /usr/local/spark-2.4.4-bin-hadoop2.7/conf/ 
root@master:~# cp /usr/local/apache-hive-2.3.6-bin/lib/mysql-connector-java-5.1.48.jar /usr/local/spark-2.4.4-bin-hadoop2.7/jars/

SparkSQL通过连接hive提供的metastore服务来获取hive表的元数据。
直接启动hive的metastore服务即可完成SparkSQL和Hive的集成。

  
  
    hive.cli.print.header
    true
  

  
  
    hive.cli.print.current.db
    true
  
  • 高可用配置
    如果hdfs配置了高可用,则还要把hadoop集群中的hdfs-site.xml和core-site.xml文件拷贝到spark/conf文件夹下面:
[root@master ~]#  cp /usr/local/hadoop-2.10.0/etc/hadoop/core-site.xml /usr/local/spark-2.4.5-bin-hadoop2.7/conf/
[root@master ~]#  cp /usr/local/hadoop-2.10.0/etc/hadoop/hdfs-site.xml /usr/local/spark-2.4.5-bin-hadoop2.7/conf/

* thrift方式集成
hvie-site.xml:

# 关闭数据库验证

    hive.metastore.schema.verification
    false

# thrift方式集成

    hive.metastore.uris
        thrift://master:9083
    None

2) Spark-Shell--Hive操作

  • HiveContext :
scala> import org.apache.spark.sql.hive.HiveContext
import org.apache.spark.sql.hive.HiveContext

scala>  val hiveContext = new HiveContext(sc);
warning: there was one deprecation warning; re-run with -deprecation for details
hiveContext: org.apache.spark.sql.hive.HiveContext = org.apache.spark.sql.hive.HiveContext@736af6f3

// 创建表
scala> hiveContext.sql("CREATE TABLE IF NOT EXISTS students (name STRING, age INT)")

  • 登录Hive查看:
// 执行结果(创建成功)
0: jdbc:hive2://192.168.71.130:10000> select * from students;
OK
+----------------+---------------+
| students.name  | students.age  |
+----------------+---------------+
+----------------+---------------+
  • Spark-Shell显示Hive内容:
// 显示hive表内容
scala> hiveContext.table("emp").show()
+-----+------+---------+----+----------+------+------+------+                   
|empno| ename|      job| mgr|  hiredate|   sal|  comm|deptno|
+-----+------+---------+----+----------+------+------+------+
| 7935|  程超|  bigdata|7902|2019-12-19|5000.0|   0.0|    40|
| 7937|牛文娟|  bigdata|7902|2019-12-19|4000.0|   0.0|    50|
| 7499|ALLEN |SALESMAN |7698|1981-02-20|1600.0| 300.0|    30|
| 7521|WARD  |SALESMAN |7698|1981-02-22|1250.0| 500.0|    30|
| 7566|JONES |MANAGER  |7839|1981-04-02|2975.0|   0.0|    20|
| 7654|MARTIN|SALESMAN |7698|1981-09-28|1250.0|1400.0|    30|
| 7698|BLAKE |MANAGER  |7839|1981-05-01|2850.0|   0.0|    30|
| 7782|CLARK |MANAGER  |7839|1981-06-09|2450.0|   0.0|    10|
| 7788|SCOTT |ANALYST  |7566|1987-07-13|3000.0|   0.0|    20|
| 7839|KING  |PRESIDENT|null|1981-11-07|5000.0|   0.0|    10|
| 7844|TURNER|SALESMAN |7698|1981-09-08|1500.0|   0.0|    30|
| 7876|ADAMS |CLERK    |7788|1987-07-13|1100.0|   0.0|    20|
| 7900|JAMES |CLERK    |7698|1981-12-03| 950.0|   0.0|    30|
| 7902|FORD  |ANALYST  |7566|1981-12-03|3000.0|   0.0|    20|
| 7934|MILLER|CLERK    |7782|1982-01-23|1300.0|   0.0|    10|
+-----+------+---------+----+----------+------+------+------+
// 数据查询
scala> hiveContext.sql("select * from default.emp").show(5,false)
+-----+------+---------+----+----------+------+-----+------+
|empno|ename |job      |mgr |hiredate  |sal   |comm |deptno|
+-----+------+---------+----+----------+------+-----+------+
|7935 |程超  |bigdata  |7902|2019-12-19|5000.0|0.0  |40    |
|7937 |牛文娟|bigdata  |7902|2019-12-19|4000.0|0.0  |50    |
|7499 |ALLEN |SALESMAN |7698|1981-02-20|1600.0|300.0|30    |
|7521 |WARD  |SALESMAN |7698|1981-02-22|1250.0|500.0|30    |
|7566 |JONES |MANAGER  |7839|1981-04-02|2975.0|0.0  |20    |
+-----+------+---------+----+----------+------+-----+------+
only showing top 5 rows

  • SparkSession:
scala> spark.sql("show tables").show(false)
+--------+---------+-----------+
|database|tableName|isTemporary|
+--------+---------+-----------+
|default |students |false      |
+--------+---------+-----------+
# 创建users表:
scala> spark.sql(("create table users(id int, name string) row format delimited fields terminated by ','"))

  • 数据:
1,zhangsan
2,lishi
3,wangwu
  • 加载数据
scala> spark.sql("LOAD DATA LOCAL INPATH '/root/users' INTO TABLE users")
scala> spark.sql("select * from users").show
+---+--------+
| id|    name|
+---+--------+
|  1|zhangsan|
|  2|   lishi|
|  3|  wangwu|
+---+--------+

二、常见问题

  1. spark java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    解决:
    拷贝jdbc jar文件到spark的jars目录下。
root@master:~# cp /usr/local/apache-hive-2.3.6-bin/lib/mysql-connector-java-5.1.48.jar /usr/local/spark-2.4.4-bin-hadoop2.7/jars/

2. Hive Schema version 1.2.0 does not match metastore's schema version 2.3.0 Metastore is not upgraded or corrupt

在hvie-site.xml中将hive.metastore.schema.verification参数设置为false:


    hive.metastore.schema.verification
    false

附:
csv,tsv,txt 文件类型区别
sv 和 csv 都是文本文件。
tsv, 是Tab-separated values的缩写,用制表符(Tab,’\t’)作为字段值的分隔符。
csv,Comma-separated values,用半角逗号(’,’)作为字段值的分隔符。

你可能感兴趣的:(Spark开发--Spark SQL--数据源(十六))