在spark上将转为常用SQL
#创建RDD。读取hdfs上的文件,按照空格分隔。若为本地则将hdfs://变为 file://
val lineRDD=sc.textFile(“hdfs://person.txt”).map(_.split(" "))
#定义表字段
case class person(id:Int,name:String,age:Int)
#将RDD和表连接
var personRDD=lineRDD.map(x=>person(x(0).toInt,x(1),x(2).toInt))
#将RDD转为DataFrame
val personDF=personRDD.toDF
#将DataFrame转为sql表
personDF.registerTempTable(“t_person”)
#进行sql语句的操作和分析,这个就比较熟悉了
spark.sqlContext.sql(“select * from t_person”)
Spark SQL
Spark SQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作用。
特点:
1.易整合
2.统一的数据访问方式
3.兼容Hive
4.标准的数据连接
DataFrame
与RDD类似,DataFrame也是一个分布式数据容器。然而DataFrame更像传统数据库的二维表格,除了数据以外,还记录数据的结构信息,即schema。同时,与Hive类似,DataFrame也支持嵌套数据类型(struct、array和map)。从API易用性的角度上 看,DataFrame API提供的是一套高层的关系操作,比函数式的RDD API要更加友好,门槛更低。由于与R和Pandas的DataFrame类似,Spark DataFrame很好地继承了传统单机数据分析的开发体验。
练习
-
在本地创建一个person.txt文件,有三列,分别是id,name,age,然后上传至hdfs上
hadoop fs -mkdir /spk_df hadoop fs -put person.txt /spk_df
-
在spark shell上执行命令,读取数据,将每一行的数据使用分隔符“ ”隔开
var lineRDD=sc.textFile("hdfs://Master:9000/spk_df/person.txt").map(_.split(" "))
-
定义case class(相当于表的schema)
case class Person(id:Int,name:String,age:Int)
-
将RDD和case class关联
val personRDD = lineRDD.map(x => Person(x(0).toInt, x(1), x(2).toInt))
-
将RDD转换成DataFrame
val personDF = personRDD.toDF
在这里我报了一个错,可能的原因版本过低的原因,在spark2.1上得到解决
错误截图为
但是依然能帮我转换成DataFrame,觉得是spark2.0最后的倔强
-
查看DataFrame
personDF.show
假如你想在练习的过程中查看数据,
出现Bug
org.apache.hadoop.ipc.RemoteException: Operation category READ is not supported in state standby
—org.apache.hadoop.ipc.remoteexception:状态待机时不支持操作类别读取
分析原因
hdfs状态必须为Active
我这里在Master上运行Spark SQL
一开始Master为Standby,Slave1为Active
修复Bug,在任何一台机都行,因为高可用。
1、将Slave1的Active强制转为Standby,nn2对应的为Slave1,之前在hdfs-size.xml中设置
hdfs haadmin -transitionToStandby -forcemanual nn2
2、将Master转换为Active,nn1对应的为Maste,之前在hdfs-size.xml中设置
hdfs haadmin -transitionToActive -forcemanual nn1
3、再次查看,成功
DataFrame常用操作
-
查看DataFrame中的内容
personDF.show
-
查看DataFrame部分列中的内容
personDF.select(personDF.col("name")).show personDF.select(col("name"), col("age")).show personDF.select("name").show
-
打印DataFrame的Schema信息
personDF.printSchema
-
查询所有的name和age,并将age+1
personDF.select(col("id"), col("name"), col("age") + 1).show personDF.select(personDF("id"), personDF("name"), personDF("age") + 1).show
-
过滤age大于等于15的
personDF.filter(col("age") >= 15).show
-
按年龄进行分组并统计相同年龄的人数
personDF.groupBy("age").count().show()
-
按年龄进行分组并统计相同年龄的人数
personDF.groupBy("age").count().show()
-
collect:获取所有数据,以数组的方式展示
personDF.collect()
-
collectAsList:获取所有数据到List
personDF.collectAsList()
-
describe() 获取字段的统计数据信息,max,min,mean,stddev等
personDF.describe("name","age","id").show()
-
where筛选操作
personDF.where("id=1 or id=2").show
-
filter过滤操作,和where的使用基本相同
personDF.filter("id =1 or id=2").show
-
select:获取指定的字段值
personDF.select("name","age")
-
selectExpr:可以对指定字段进行特殊处理 ,对name列进行更换别名
personDF.selectExpr("id","name as make").show(true)
-
drop 删除其中一列,一次只能去除一个字段。
val drop_person=personDF.drop("id")
drop_person.show
-
groupBy,orderBy分组筛选
personDF.groupBy(personDF("age")).count().orderBy(personDF("age").desc).show()
-
distinct 返回一个不含重复值的Dataframe
personDF.distinct()
-
重命字段名,本身的personDF是不变的
personDF.withColumnRename("id","ids").printSchema
本身的personDF是不变的
-
增加列,本身的personDF是不变的
personDF.withColumn("id2",personDF("id")).show()
DataFrame常用操作-SQL风格语法
创建一个sqlContext
var sqlContext=new org.apache.spark.sql.SQLContext(sc)
想使用SQL风格的语法,需要将DataFrame注册成表
personDF.registerTempTable("t_person")
查询年龄最大的前两名
sqlContext.sql("select * from t_person order by age desc limit 2").show
显示表的Schema信息
sqlContext.sql("desc t_person").show