1. Import  spark.implicits._ 的作用

支持在DataFrame中使用 $”列名” 这个语法糖,表示的是Column对象

df.select($"name").show()

如果不加$,那么就会当一个String来处理

 

支持把一个RDD隐式转换为一个DataFrame

---- 引申: 目前Spark官网提供了三种方法来实现从RDD转DataFrame

1.1 直接指定列名,让Spark自动推断类型

spark sql 注入变量 spark sql 传参_json

1.2利用反射机制推断RDD模式

需要一个case class 还有上面那个导入,然后RDD就可以用.toDF了

1.3使用编程方式定义RDD模式

无法提前定义case class时,采用编程的方式定义RDD,即定义: val schema = StructType(StructField(name,StringType,true), StructField(age,StringType,true))

接着使用spark.createDataFrame(RDD,schema)即可


ps:如果是DataSet的话,只能用1.2和1.3的方式,因为DataSet是一个typed transformations,在代码中就要指定好数据的类型,它的类型检查是在编译期完成的,而DataFrame是Untyped transformations,它的类型检查是在运行期完成的

 

2. 报错有个包找不到 org.spark_project.guava.util.concurrent.ExecutionError: java.lang.NoClassDefFoundError:org/codehaus/commons/compiler/UncheckedCompileException

将SparkSQL自身的那两个包排掉,换成网页中提到的3.0.7的包

`<dependency>
  <groupId>org.apache.spark</groupId>
  <artifactId>spark-sql_2.11</artifactId>
  <version>2.1.1</version>
  <exclusions>
   <exclusion>
     <groupId>org.codehaus.janino</groupId>
     <artifactId>janino</artifactId>
   </exclusion>
   <exclusion>
     <groupId>org.codehaus.janino</groupId>
     <artifactId>commons-compiler</artifactId>
   </exclusion>
  </exclusions>
 </depenedency>
 <dependency>
   <groupId>org.codehaus.janino</groupId>
   <artifactId>commons-compiler</artifactId>
   <version>3.07</version>
 </dependency>
 <dependency>
   <groupId>org.codehaus.janino</groupId>
   <artifactId>janino</artifactId>
   <version>3.07</version>
 </dependency>`

 

3.    看来spark读取json文件的话,会自己构建一个schema,不需要自己外部隐式定义一个case class什么了.(验证过了,是对的)

 

注意这个import, 导入的不是类,而是sparkSession这个变量里面的东西,sparkSession是你自己创建的SparkSession

 

 

4.     DataFrame使用SQL语句

注册成表的性能会比直接操作DataSet快还是慢?)

         注册成的表有两种类型:

                  5.1.1  LocalTempView

                  5.1.2  GlobalTempView

         两者的区别在于它们的生命周期,LocalTempView生命周期和sparksession生命周期相同,使用时通过sparksession变量调用即可. 而另外一个是注册在一个叫global_temp这张系统表上的,可以在多个session中共享,使用的时候需要用SELECT * FROM global_temp.people.

         5.2 还需要import sparkSession.implicits._,不然也是不能使用SQL语句的

 

DataFrame中的每一个元素都是一个Row,代表一行数据

 

6.     Datasets

每定义一种类型的Datasets,就需要编写对应的Encoder类,不然会报错!.

 

---- 引申: 目前Spark官网提供了两种方法来实现从RDD转Dataset,和上面的DataFrame几乎是一样的…

1.1利用反射机制推断RDD模式

需要一个case class 还有上面那个导入,然后RDD转为DataFrame

因为DataFrame和DataSet可以相互转化,df.as[ElementType]这样可以把DataFrame

转化为DataSet,ds.toDF()这样可以把DataSet转化为DataFrame。

                  或者直接转为DataSet spark.read.json(path).as[Person]

 

1.2使用编程方式定义RDD模式

                  比RDD转DataFrame要麻烦点,想要将original RDD -> RDD[Row]的结构,然后创建对应的StructType, spark.createDataFrame(rowRDD, schema)… 这不还是转成DataFrame么?!

DF就自动变成DataSet了!

根本就没有直接转成Datasets的方法,RDD只能先转成DataFrame,然后再转换到DataSet…

 

7.parquet merge schema的理解

         即数据集合并,相当于是做笛卡尔积(全连接). 可以分散在两个文件中,也可以在同一个文件中.

         合并规则为:

                  7.1 相同的列,在新的数据集中,是通用的列

                  7.2 各自不同的列,作为新的数据集的列

 


 

再引申说一点parquet的东西:

         Parquet是一种基于列式存储的结构,列式存储因为同一列的很多内容可能相同,所以易于压缩,间接的减少了磁盘IO,并且支持分区等功能(如果业务中只是读取少量的列的话,是非常适合用parquet的!)

分区发现—需要深入去理解下,不懂这个机制)

 

 

8.Data Source为JSON

         Schema也不需要写,会自动检测出来,并且spark.read.json(path),获取的直接是DataSet[ROW]的结构.

 

9.使用dataframe.cache的时候,压缩默认为true