1.了解Spark Shell、Spark SQL模式
2.学习使用Spark Shell、Spark SQL模式,创建表及查询数据
实验原理
Spark SQL的前身是Shark,Shark是伯克利实验室Spark生态环境的组件之一,它能运行在Spark引擎上,从而使得SQL查询的速度得到10-100倍的提升,但是,随着Spark的发展,由于Shark对于Hive的太多依赖(如采用Hive的语法解析器、查询优化器等等),制约了Spark的One Stack Rule Them All的既定方针,制约了Spark各个组件的相互集成,所以提出了SparkSQL项目。
SparkSQL抛弃了原有Shark的代码,汲取了Shark的一些优点,如内存列存储(In-MemoryColumnarStorage)、Hive兼容性等,重新开发了SparkSQL代码;由于摆脱了对Hive的依赖性,SparkSQL无论在数据兼容、性能优化、组件扩展方面都得到了极大的方便。
(Spark SQL 执行流程)
SQLContext具体的执行过程如下:
(1)SQL | HQL语句经过SqlParse解析成UnresolvedLogicalPlan。
(2)使用analyzer结合数据字典(catalog)进行绑定,生成resolvedLogicalPlan,在这个过程中,Catalog提取出SchemRDD,并注册类似case class的对象,然后把表注册进内存中。
(3)Analyzed Logical Plan经过Catalyst Optimizer优化器优化处理后,生成Optimized Logical Plan,该过程完成以后,以下的部分在Spark core中完成。
(4)Optimized Logical Plan的结果交给SparkPlanner,然后SparkPlanner处理后交给PhysicalPlan,经过该过程后生成Spark Plan。
(5)使用SparkPlan将LogicalPlan转换成PhysicalPlan。
(6)使用prepareForExecution()将PhysicalPlan转换成可执行物理计划。
(7)使用execute()执行可执行物理计划。
(8)生成DataFrame。
在整个运行过程中涉及到多个SparkSQL的组件,如SqlParse、analyzer、optimizer、SparkPlan等等。
实验环境
Linux Ubuntu 16.04
jdk-7u75-linux-x64
hadoop-2.6.0-cdh5.4.5
scala-2.10.5
spark-1.6.0-bin-hadoop2.6
实验内容
某电商平台,需要对订单数据进行分析,已知订单数据包括两个文件,分别为订单数据orders和订单明细数据order_items,orders记录了用户购买商品的订单ID,订单号,用户ID及下单日期。order_items记录了商品ID,订单ID以及明细ID。它们的结构与关系如下图所示:
实验步骤
1.首先检查Hadoop相关进程,是否已经启动。若未启动,切换到/apps/hadoop/sbin目录下,启动Hadoop。
- jps
- cd /apps/hadoop/sbin
- ./start-all.sh
2.在Linux本地新建/data/spark5目录。
- mkdir -p /data/spark5
3.切换到/data/spark5目录下,使用wget命令,下载http://172.16.103.12:60000/allfiles/spark5中的orders和order_items。
- cd /data/spark5
- wget http://172.16.103.12:60000/allfiles/spark5/orders
- wget http://172.16.103.12:60000/allfiles/spark5/order_items
4.首先,在HDFS上新建/myspark5目录,然后将/data/spark5目录下的orders与order_items文件,上传到HDFS的/myspark5目录下。
- hadoop fs -mkdir /myspark5
- hadoop fs -put /data/spark5/orders /myspark5
- hadoop fs -put /data/spark5/order_items /myspark5
5.启动Spark Shell。
- spark-shell
6.在spark-shell下,使用case class方式定义RDD,创建orders表。
- val sqlContext = new org.apache.spark.sql.SQLContext(sc)
- import sqlContext.implicits._
- case class Orders(order_id:String,order_number:String,buyer_id:String,create_dt:String)
- val dforders = sc.textFile("/myspark5/orders").map(_.split('\t')).map(line=>Orders(line(0),line(1),line(2),line(3))).toDF()
- dforders.registerTempTable("orders")
验证创建的表是否成功。
- sqlContext.sql("show tables").map(t=>"tableName is:"+t(0)).collect().foreach(println)
- sqlContext.sql("select order_id,buyer_id from orders").collect
7.在Spark Shell下,使用applyScheme方式定义RDD,创建order_items表。
- import org.apache.spark.sql._
- import org.apache.spark.sql.types._
- val rddorder_items = sc.textFile("/myspark5/order_items")
- val roworder_items = rddorder_items.map(_.split("\t")).map( p=>Row(p(0),p(1),p(2) ) )
- val schemaorder_items = "item_id order_id goods_id"
- val schema = StructType(schemaorder_items.split(" ").map(fieldName=>StructField(fieldName,StringType,true)) )
- val dforder_items = sqlContext.applySchema(roworder_items, schema)
- dforder_items.registerTempTable("order_items")
验证创建表是否成功。
- sqlContext.sql("show tables").map(t=>"tableName is:"+t(0)).collect().foreach(println)
- sqlContext.sql("select order_id,goods_id from order_items ").collect
8.将order表及order_items表进行join操作,统计该电商网站,都有哪些用户购买了什么商品。
- sqlContext.sql("select orders.buyer_id, order_items.goods_id from order_items join orders on order_items.order_id=orders.order_id ").collect
9.退出Spark shell模式
- exit
下面演示Spark SQL模式
10.启动Spark SQL。
- spark-sql
11.创建表orders及表order_items。
- create table orders (order_id string,order_number string,buyer_id string,create_dt string)
- row format delimited fields terminated by '\t' stored as textfile;
- create table order_items(item_id string,order_id string,goods_id string)
- row format delimited fields terminated by '\t' stored as textfile;
12.查看已创建的表。
- show tables;
表名后的false意思是该表不是临时表。
13.将HDFS中/myspark5下的orders表和order_items表中数据加载进刚创建的两个表中。
- load data inpath '/myspark5/orders' into table orders;
- load data inpath '/myspark5/order_items' into table order_items;
14.验证数据是否加载成功。
- select * from orders;
- select * from order_items;
15.处理文件,将order表及order_items表进行join操作,统计该电商网站,都有哪些用户购买了什么商品。
- select orders.buyer_id, order_items.goods_id from order_items join orders on order_items.order_id=orders.order_id;