问题导读
1、Spark SQL多了一个什么重要的功能?
2、Spark SQ支持哪些关系型查询表达式?
Spark1.0出来了,变化还是挺大的,文档比以前齐全了,RDD支持的操作比以前多了一些,Spark on yarn功能我居然跑通了。但是最最重要的就是多了一个Spark SQL的功能,它能对RDD进行Sql操作,目前它只是一个alpha版本,喜欢尝鲜的同志们进来看看吧,下面是它的官网的翻译。
Spark SQL是支持在Spark中使用Sql、HiveSql、Scaca中的关系型查询表达式。它的核心组件是一个新增的RDD类型SchemaRDD,它把行对象用一个Schema来描述行里面的所有列的数据类型,它就像是关系型数据库里面的一张表。它可以从原有的RDD创建,也可以是Parquet文件,最重要的是它可以支持用HiveQL从hive里面读取数据。
下面是一些案例,可以在Spark shell当中运行。
首先我们要创建一个熟悉的Context,熟悉spark的人都知道吧,有了Context我们才可以进行各种操作。
- val sc: SparkContext // 已经存在的SparkContext
- val sqlContext = new org.apache.spark.sql.SQLContext(sc)
-
- import sqlContext._
复制代码
Running SQL on RDDs
Spark SQL支持的一种表的类型是Scala的case class,case class定义了表的类型,下面是例子:
- val sqlContext = new org.apache.spark.sql.SQLContext(sc)
- import sqlContext._
-
- // case class在Scala 2.10里面最多支持22个列,,为了突破这个现实,最好是定义一个类实现Product接口
- case class Person(name: String, age: Int)
-
- // 为Person的对象创建一个RDD,然后注册成一张表
- val people = sc.textFile("examples/src/main/resources/people.txt").map(_.split(",")).map(p => Person(p(0), p(1).trim.toInt))
- people.registerAsTable("people")
-
- // 直接写sql吧,这个方法是sqlContext提供的
- val teenagers = sql("SELECT name FROM people WHERE age >= 13 AND age <= 19")
-
- // teenagers是SchemaRDDs类型,它支持所有普通的RDD操作
- teenagers.map(t => "Name: " + t(0)).collect().foreach(println)
复制代码
从上面这个方法来看,不是很好用,一个表好几十个字段,我就得一个一个的去赋值,它现在支持的操作都是很简单的操作,想要实现复杂的操作可以具体去看HiveContext提供的HiveQL。
Using Parquet
- val sqlContext = new org.apache.spark.sql.SQLContext(sc)
- import sqlContext._
-
- val people: RDD[Person] = ... // 同上面的例子.
-
- // 这个RDD已经隐式转换成一个SchemaRDD, 允许它存储成Parquet格式.
- people.saveAsParquetFile("people.parquet")
-
- // 从上面创建的文件里面读取,加载一个Parquet文件的结果也是一种JavaSchemaRDD.
- val parquetFile = sqlContext.parquetFile("people.parquet")
-
- //注册成表,然后使用
- parquetFile.registerAsTable("parquetFile")
- val teenagers = sql("SELECT name FROM parquetFile WHERE age >= 13 AND age <= 19")
- teenagers.collect().foreach(println)
复制代码
Writing Language-Integrated Relational Queries
目前这个功能只是在Scala里面支持,挺鸡肋的一个功能
- val sqlContext = new org.apache.spark.sql.SQLContext(sc)
- import sqlContext._
- val people: RDD[Person] = ... // 同前面的例子.
-
- // 和后面这个语句是一样的 'SELECT name FROM people WHERE age >= 10 AND age <= 19'
- val teenagers = people.where('age >= 10).where('age <= 19).select('name)
复制代码
Hive Support
这下面的才是高潮,它可以从hive里面取数据。但是hive的依赖太多了,默认Spark assembly是没带这些依赖的,需要我们运行SPARK_HIVE=true sbt/sbt assembly/assembly重新编译,或者用maven的时候添加-Phive参数,它会重新编译出来一个hive assembly的jar包,然后需要把这个jar包放到所有的节点上。另外还需要把hive-site.xml放到conf目录下。没进行hive部署的话,下面的例子也可以用LocalHiveContext来代替HiveContext。
- val sc: SparkContext // 已经存在的SparkContext
- val hiveContext = new org.apache.spark.sql.hive.HiveContext(sc)
-
- // 引入这个Context,然后就会给所有的sql语句进行隐式转换
- import hiveContext._
-
- hql("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)")
- hql("LOAD DATA LOCAL INPATH 'examples/src/main/resources/kv1.txt' INTO TABLE src")
-
- // 使用HiveQL查询
- hql("FROM src SELECT key, value").collect().foreach(println)
复制代码
这个功能看起来还挺像样,前面两个看起来就像渣一样,没劲儿,不知道为什么不自带那些依赖,还要我们再编译一下,但是我下的那个版本运行的时候提示我已经编译包括了hive的。尼玛,真恶心。
|