Spark SQL 简单使用

环境:scala 版本2.11.8,spark 版本2.0.1,使用 Intellij IDEA 来开发。 
准备工作:

创建maven项目

可以从官网上找到我们建项目时使用的 archetype 
这里写图片描述 
至于具体怎么创建项目,请参考一个朋友的文章Intellij IDEA 创建 spark/scala 项目 
这个是前一段时间发现的一个朋友,强烈推荐大家去转转。 
好了,这样一来就默认大家创建好了项目…

1 第一个例子

1.1 创建 SparkSession

这里写图片描述
官方文档如是说。 
那么我们可以按照这个例子来写。

import org.apache.spark.sql.SparkSession

val spark = SparkSession
            .builder()
            .appName("sql test")
            .master("local")
            .getOrCreate()

import spark.implicits._            
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

1.2 创建 DataFrames

这里写图片描述

//创建dataframe
val df = spark.read.json("C:\\Users\\Administrator\\Desktop\\people.json")

df.show()
// +----+-------+
// | age|   name|
// +----+-------+
// |null|Michael|
// |  30|   Andy|
// |  19| Justin|
// +----+-------+
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

就像官网写的那样,我们可以调用 show() 方法来打印出 df 的数据。这里我是把官网上的示例给放到了指定的目录。当然,我们也可以自己创建一个 json 文件,格式如下:

{"name":"Signal"}
{"name":"May j Lee","age":20}
{"name":"Jay Chou","age":36}
{"name":"Jack Chen","age":60}
  • 1
  • 2
  • 3
  • 4
  • 5

当然,还有一些其他操作,我就不一一敲了,官网上给出的示例非常详细。用到类似的了就去官网上查… 
这里写图片描述

我们还可以使用 SQL 语句来操作: 
这里写图片描述

不过在我们使用 SQL 进行操作之前,需要使用 createOrReplaceTempView() 方法,熟悉 SQL 语句人肯定都知道”视图(view)“,接下来这个就是我们要操作的对象。

df.createOrReplaceTempView("people")
val sqlDF = spark.sql("select * from people")
sqlDF.show()
  • 1
  • 2
  • 3

2 第二个例子

在第一个例子中,我们是根据一个 json 文件进行了一系列的操作,接下来我们是不是可以创建一个呢?

这里我们需要使用到的对象是 DataSets

2.1 创建 DataSets

这里写图片描述

我们还是参照官网的例子来写:

def createDataSetsTest(spark:SparkSession): Unit ={
  import spark.implicits._

  //创建 DataSet
  val caseClassDS = Seq(Person("Jack",80),Person("Rose",76)).toDS()
  caseClassDS.show()

  //保存
  caseClassDS.write.mode(SaveMode.Overwrite).json("C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\person.json")

  val primitiveDS = Seq(1,2,3).toDS()
  val ds = primitiveDS.map(_+1).collect()
  ds.foreach(println)

  val path = "C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\person.json"
  val personDS = spark.read.json(path).as[Person]

  personDS.show()

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

接下我们可以调用这个 createDataSets(…) 来看看到底发生了些什么事情。

object SqlJson {
  case class Person(name:String,age:Long)

  def main(args: Array[String]) {
    val spark = SparkSession.builder().appName("spark json").master("local").getOrCreate()

    import spark.implicits._

    createDataFrameTest(spark)
  }
}  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这里写图片描述

于是就像图片上那样,我们成功保存了 json 对象,并且我们还将它输出到了控制台。

这里写图片描述

这里大家可能疑惑的就是 SavaMode 了,别担心,官网有: 
这里写图片描述

说起来保存,我们还可以保存为 parquet。 
这里写图片描述

...
//保存
df.write.mode(SaveMode.Overwrite).parquet("C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\sparkSql.parquet")

//读取
val parquetFile = spark.read.parquet("C:\\Users\\Administrator\\Desktop\\SIGNAL-TEMP\\sparkSql.parquet")

parquetFile.where($"key"===1).select($"key",$"value".as("v")).collect().foreach(println)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

同样的,会在我们指定的路径下新建一个文件夹: 
这里写图片描述

但是对于这个文件就没有那么友好了,我们看不懂^@^

3 Spark 与 Hive

我们可以通过 Spark 在 Hive 中创建一张表,并且导入数据。 
这次我们需要将代码打成 jar 包,放到集群下去运行。

package spark.connect

import org.apache.spark.sql.SparkSession

/**
  * Created by SIGNAL on 2016/11/28.
  */
object HiveTest {
  val spark = SparkSession.builder().appName("Spark connect to Hive").enableHiveSupport().getOrCreate()

  def main(args: Array[String]) {
    import spark.implicits._
    import spark.sql

    val createTable = "create table if not exists spark_hive_test(col1 int,col2 string,col3 string) row format delimited fields terminated by '|'"
    spark.sql(createTable)
    sql("load data local inpath '/home/signal/spark_hive_test.txt' overwrite into table spark_hive_test")

    val df = sql("select * from spark_hive_test")

    df.show()

    spark.stop()

  }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

Intellij IDEA 打 jar 包比较麻烦,不如 Eclipse 来的顺溜。 
Ctrl + Alt + Shift + s 之后,出现 Project Structure,然后如图,然后自己倒腾… 
这里写图片描述

…于是经过一番折腾之后,我以为大家 jar 包打好了。 
然后我们可以发送到Linux上,方便操作就放到 master 节点上的 /homa/signal 目录下了: 
这里写图片描述

大家还记得 hive 的建表语法吧,记得我们在建表时指定的分割符是什么不? 
这里写图片描述

可以看到我们指定的分割符是”|“,而且,导入到 hive 中的时候我们指定了文件名和文件的路径,也就我们当前所在的 /home/signal,接下来我们需要在 /home/siganl 目录下创建一个 spark_hive_test.txt 的文件,文件格式如下:

[root@master signal]# vi spark_hive_test.txt 
4|Signal|male
5|Kevin|male
6|Max|female

"spark_hive_test.txt" 3L, 40C written
[root@master signal]# 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

这一系列操作完了之后,我们就可以运行 spark-submit 了。但是,我们需要确保的是 Mysql 的服务是启动的。

[root@master signal]# service mysql status
 SUCCESS! MySQL running (1678)

[root@master signal]# 
  • 1
  • 2
  • 3
  • 4

那么我们就”提交“吧: 
这里写图片描述

[root@master signal]# spark-submit --class spark.connect.HiveTest --master[1] SparkHive.jar

...
+----+------+------+
|col1|  col2|  col3|
+----+------+------+
|   4|Signal|  male|
|   5| Kevin|  male|
|   6|   Max|female|
+----+------+------+

16/11/28 19:46:35 INFO SparkUI: Stopped Spark web UI at http://192.168.38.129:4040
16/11/28 19:46:35 INFO MapOutputTrackerMasterEndpoint: MapOutputTrackerMasterEndpoint stopped!
16/11/28 19:46:35 INFO MemoryStore: MemoryStore cleared
16/11/28 19:46:35 INFO BlockManager: BlockManager stopped
16/11/28 19:46:35 INFO BlockManagerMaster: BlockManagerMaster stopped
16/11/28 19:46:35 INFO OutputCommitCoordinator$OutputCommitCoordinatorEndpoint: OutputCommitCoordinator stopped!
16/11/28 19:46:35 INFO SparkContext: Successfully stopped SparkContext
16/11/28 19:46:35 INFO ShutdownHookManager: Shutdown hook called
16/11/28 19:46:35 INFO ShutdownHookManager: Deleting directory /tmp/spark-59c859cc-611b-4aac-adce-567eb8376ffa
[root@master signal]# 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

控制台是正常输出了,我们可以到 Hive 中看看是否真的创建成功了。 
启动 hiveserver2,然后使用 beeline 访问:

[root@master bin]# hiveserver2 & > /dev/null 2>&1 
[1] 7712

[root@master bin]# beeline -u jdbc:hive2://master:10000 -n root
...
Connected to: Apache Hive (version 2.1.0)
Driver: Hive JDBC (version 2.1.0)
16/11/28 19:56:12 [main]: WARN jdbc.HiveConnection: Request to set autoCommit to false; Hive does not support autoCommit=false.
Transaction isolation: TRANSACTION_REPEATABLE_READ
Beeline version 2.1.0 by Apache Hive
0: jdbc:hive2://master:10000>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这里写图片描述

我们可以看到,在 default 下是有 spark_hive_test 这张表的。

0: jdbc:hive2://master:10000> use default;
OK
No rows affected (0.243 seconds)

0: jdbc:hive2://master:10000> select * from spark_hive_test;
OK
+-----------------------+-----------------------+-----------------------+--+
| spark_hive_test.col1  | spark_hive_test.col2  | spark_hive_test.col3  |
+-----------------------+-----------------------+-----------------------+--+
| 4                     | Signal                | male                  |
| 5                     | Kevin                 | male                  |
| 6                     | Max                   | female                |
+-----------------------+-----------------------+-----------------------+--+
3 rows selected (2.319 seconds)
0: jdbc:hive2://master:10000> 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

真的就像我们在控制台里看到的那样,我们的hive中有了那张表,并且数据也加载进去了。

4 Spark 与 HBase

package spark.connect

import org.apache.hadoop.hbase.HBaseConfiguration
import org.apache.hadoop.hbase.client.Result
import org.apache.hadoop.hbase.io.ImmutableBytesWritable
import org.apache.hadoop.hbase.mapreduce.TableInputFormat
import org.apache.hadoop.hbase.util.Bytes
import org.apache.spark.{SparkConf, SparkContext}

/**
  * Created by SIGNAL on 2016/11/28.
  */
object HBaseTest {
  val conf = new SparkConf().setAppName("Spark connect to HBase").setMaster("local")
  val sc = new SparkContext(conf)


  def main(args: Array[String]) {
    val hconf = HBaseConfiguration.create()
    hconf.set(TableInputFormat.INPUT_TABLE,"student")

    val hbaseRDD = sc.newAPIHadoopRDD(hconf,classOf[TableInputFormat]
      ,classOf[ImmutableBytesWritable]
      ,classOf[Result])

    val rowRDD = hbaseRDD.map(x =>(Bytes.toString(x._1.get()), Bytes.toString(x._2.getValue("i".getBytes,"name".getBytes()))))

    println(hbaseRDD.count())

    rowRDD.foreach(println _)

    sc.stop()
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

这个就没什么好说的了,跟我们使用 java 访问 HBase 差不太多,只不过我们这次使用的是 scala 。 
确保我们的 hbase 启动,我们就可以在 Intellij IDEA 中运行了。 
这里写图片描述

然后运行,我们会在控制台上看到 student 表中 i 列族下的 name 一列的数据了: 
这里写图片描述

当然,我们有好多种运行方式,可以放到集群中去运行,还可以在 yarn 下运行。大家可以参照官网上 spark-submit 来操作,就不一一演示了。

5 Spark 与 Mysql

package spark.connect

import java.sql.{Connection, DriverManager}
import java.util.Properties

import org.apache.spark.rdd.JdbcRDD
import org.apache.spark.sql.SparkSession
import org.apache.spark.{SparkConf, SparkContext}

/**
  * Created by SIGNAL on 2016/11/28.
  */
object MysqlTest {
  val conf = new SparkConf().setAppName("Spark connect to Mysql").setMaster("local")
  val sc = new SparkContext(conf)

  def createConnection(): Connection ={
    Class.forName("com.mysql.jdbc.Driver").newInstance()
//    DriverManager.getConnection("jdbc:mysql://localhost:3306/test?user=root&password=signal")
    DriverManager.getConnection("jdbc:mysql://localhost:3306/test","root","signal")

  }

  def formMysql(): Unit ={
    val spark = SparkSession.builder.appName("spark connect to mysql").master("local").getOrCreate()

    import spark.implicits._

    val fromrd = spark.read.jdbc("jdbc:mysql://localhost:3306/gov?user=root&password=signal","app_user",new Properties())
    fromrd.show()
  }

  def main(args: Array[String]): Unit = {
    val mysqlData = new JdbcRDD(sc,createConnection,"select * from tb_user where user_id >= ? and user_id <= ? ",0,1000,3,r=>r)

    mysqlData.map(r => (r.getLong("user_id"),r.getInt("age"),r.getString("user_name") )).foreach(println _)

  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

这个跟 HBase 一样,都是比较简单的操作,但是我只是从数据库中读取数据,往数据库中写数据都差不多,看看 API 很快就会上手,也就不写了。

这么一来,Spark SQL 也就介绍的差不多了,大家还有看不懂的就去看官方文档吧,多看看,对着敲几遍代码,去 API 里看看方法。

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/M_SIGNALs/article/details/53380786
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页