Spark入门之六:SparkSQL实战

  1. 介绍

    SparkSQL引入了一种新的RDD——SchemaRDDSchemaRDD由行对象(Row)以及描述行对象中每列数据类型的Schema组成;SchemaRDD很象传统数据库中的表。SchemaRDD可以通过RDDParquet文件、JSON文件、或者通过使用hiveql查询hive数据来建立。SchemaRDD除了可以和RDD一样操作外,还可以通过registerTempTable注册成临时表,然后通过SQL语句进行操作。

    值得注意的是:

    lSpark1.1使用registerTempTable代替1.0版本的registerAsTable

    lSpark1.1hiveContext中,hql()将被弃用,sql()将代替hql()来提交查询语句,统一了接口。

    l使用registerTempTable注册表是一个临时表,生命周期只在所定义的sqlContexthiveContext实例之中。换而言之,在一个sqlContext(或hiveContext)中registerTempTable的表不能在另一个sqlContext(或hiveContext)中使用。

    另外,Spark1.1提供了语法解析器选项spark.sql.dialect,就目前而言,Spark1.1提供了两种语法解析器:sql语法解析器和hiveql语法解析器。

    lsqlContext现在只支持sql语法解析器(SQL-92语法)

    lhiveContext现在支持sql语法解析器和hivesql语法解析器,默认为hivesql语法解析器,用户可以通过配置切换成sql语法解析器,来运行hiveql不支持的语法,如select 1

    l切换可以通过下列方式完成:

    lsqlContexet中使用setconf配置spark.sql.dialect

    lhiveContexet中使用setconf配置spark.sql.dialect

    lsql命令中使用 set spark.sql.dialect=value

    SparkSQL1.1对数据的查询分成了2个分支:sqlContext  hiveContext。至于两者之间的关系,hiveSQL继承了sqlContext,所以拥有sqlontext的特性之外,还拥有自身的特性(最大的特性就是支持hive)。


  2. 演示版本:spark-1.4.1-bin-hadoop2.6
  3. sqlContext
    1. 使用Case Class定义RDD
      1. 介绍
        对于Case Class方式,首先要定义Case Class,在RDDTransform过程中使用Case Class可以隐式转化成SchemaRDD,然后再使用registerTempTable注册成表。注册成表后就可以在sqlContext对表进行操作,如select insertjoin等。注意,case class可以是嵌套的,也可以使用类似Sequences  Arrays之类复杂的数据类型。
      2. 演示代码
        scala> val sqlContext = new org.apache.spark.sql.SQLContext(sc)
        scala> import sqlContext.implicits._
        scala> case class Person(name:String,age:Int)
        scala> val people=sc.textFile("hdfs://cloud25:9000/data/people.txt").map(_.split(",")).map(p=>Person(p(0),p(1).trim.toInt)).toDF()
        scala> teenagers.map(t => "Name: " + t(0)).collect().foreach(println)
    2. parquest演示
      1. 介绍
        sqlContext可以读取parquet文件,由于parquet文件中保留了schema的信息,所以不需要使用case class来隐式转换。sqlContext读入parquet文件后直接转换成SchemaRDD,也可以将SchemaRDD保存成parquet文件格式。
      2. 演示代码
        scala> import sqlContext.implicits._
        scala> sqlContext.setConf("spark.sql.parquet.binaryAsString", "true") //解决文件中parquet中binary字段的问题
        scala> val wikiData = sqlContext.parquetFile("hdfs://cloud25:9000/data/wiki_parquet").toDF()
        scala> wikiData.count()
        scala> wikiData.registerTempTable("wikidata")
        scala> val countResult = sqlContext.sql("SELECT COUNT(*) FROM wikiData").collect()
        scala> val queryResult= sqlContext.sql("SELECT username, COUNT(*) AS cnt FROM wikiData WHERE username <> '' GROUP BY username ORDER BY cnt DESC LIMIT 10")
        scala> queryResult.collect().foreach(println)
    3. Join演示
      1. 介绍
        sqlContext可以从多个种类的SchemaRDD中执行join操作
      2. 演示代码
        scala> val sqlContext = new org.apache.spark.sql.SQLContext(sc)
        scala> import sqlContext.implicits._
        scala> case class Person(name:String,age:Int)
        scala> val people=sc.textFile("hdfs://cloud25:9000/data/people.txt").map(_.split(",")).map(p=>Person(p(0),p(1).trim.toInt)).toDF()
        scala> people.saveAsParquetFile("hdfs://cloud25:9000/data/people.parquet")
        scala> val parquetFile = sqlContext.parquetFile("hdfs://cloud25:9000/data/people.parquet")
        scala> people.registerTempTable("people")
        scala> parquetFile.registerTempTable("parquetFile")
        scala> val jointbls = sqlContext.sql("SELECT people.name FROM people join parquetFile where people.name=parquetFile.name")
        scala> jointbls.collect.foreach(println)
  4. hiveContext
    1. 描述
      到1.4.1一版本,可以动过两种方式与hive集成,第一种是使用已经部署好的metastore,如果使用这种方式需要在spark中添加hive的相关配置,第二种:如果没有配置相关的信息,hiveContext会在当前目录自己创建metadata_db以及warehouse 
    2. 配置过程
      以下配置流程仅仅针对描述中的第一种情况(使用已有metastore)
      1. 后台启动metasore服务
      2. 创建/opt/cloud/spark-1.4.1-bin-hadoop2.6/conf/hive-site.xml文件,并编辑内容如下:
         
         
         
           
            hive.metastore.uris 
            thrift://cloud25:9083 
            Thrift URI for the remote metastore. Used by metastore client to connect to remote metastore. 
           
        
      3. 启动spark-shell:./spark-shell --master=spark://cloud25:7077 --executor-memory=2g
    3. 代码演示
      1. 使用已有metastore的代码
        scala> val hiveContext = new org.apache.spark.sql.hive.HiveContext(sc)
        scala> hiveContext.sql("select count(*) from SOGOUQ1 where S_SEQ=1 and C_SEQ=2").collect.foreach(println)
         scala> hiveContext.sql("select count(*) from SOGOUQ1 where S_SEQ=1 and C_SEQ=2 and WEBSITE like '%baidu%'").collect.foreach(println)
        scala> hiveContext.sql("select WEBSESSION,count(WEBSESSION) as cw from SOGOUQ1 group by WEBSESSION order by cw desc limit 10").collect.foreach(println)
      2. 独立维护metastore的代码
        scala> val hiveContext = new org.apache.spark.sql.hive.HiveContext(sc)
        scala> hiveContext.sql("CREATE TABLE IF NOT EXISTS src (key INT, value STRING)")
    4. 性能比较
      下列的表格给出了hive基于hadoop以及spark的性能对比,由于都没有Hadoop,Spark集群都没有做优化,所以结果仅供参考
      语句 hive on hadoop(s) hive on spark(s)
      Select count(*) from SOGOUQ1; 29.291 2.496752
      select count(*) from SOGOUQ1 where S_SEQ=1 and C_SEQ=2; 26.421 2.83421
      select count(*) from SOGOUQ1 where S_SEQ=1 and C_SEQ=2
       and WEBSITE like '%baidu%';
      26.122 1.692844
      select WEBSESSION,count(WEBSESSION) as cw from 
      SOGOUQ1 group by WEBSESSION order by cw desc limit 10;
      56.313 5.857438

你可能感兴趣的:(Spark,Spark入门简单学,SparkSQL,hiveContext,sqlContext)