今天是Catalyst部分的收官,主要讲一些杂项内容。算法
什么叫外部数据源,是SparkSql本身支持的一些文件格式,以及一些本身自定义格式的文件开发。数据库
让咱们从文件的读取api开始,能够看到最终会建立一个DataFrame,当中比较关键的是relation方法。编程
首先,会以反射方式获取provider。json
咱们以json文件为例,其provider为json.DefaultSource。能够看到继承自HadoopFsRelationProvider。api
进入其处理,能够看到,首先是获取文件路径,其后是调用了createRelation方法。缓存
让咱们进入json.DefaultSource的createRelation,建立了JSONRelation。服务器
JSONRelation继承自HadoopFsRelation,来自interfaces.scala,定义了对各种文件的处理接口。markdown
最终JSONRelation组合入LogicalRelation中,提供后续解析器处理。数据结构
简单来讲,处理流程是:jvm
在optimizer中,对于文件的操做,在执行过程当中还支持过滤下推,根据算子生成下推条件。
filters中定义了一系列算子,能够在服务器上直接过滤数据,而不是集中到客户端过滤。
咱们看下缓存,不少算法都是缓存+并行来作的,是一个开发者逃不掉的魔咒,在Catalyst中直接cacheTable就能够缓存。
缓存在内存中,是以什么方式存储的?确定是列式存储的方式,由于列式存储检索数据特别快,不是RDD一行一行object存放的方式,缓存的时候,对象会进入jvm的老年代,很容易产生full GC,进行交互查询容易悲剧。基于列的话,就能够采用相似byteBuffer这样的方式,因为是一样的数据类型,能够进行压缩,内存占用会极大的减小。查询的时候,只使用部分列也是一个天然的思路。
让咱们看一下代码:首先进入cacheTable方法。
最重要的是对InMemoryRelation的生成。
InMemoryRelation继承自LogicalPlan,其方法都是一些简单的基于字节的编程
内部作cache的时候,根据构建的树,会采用mapPartitions的方式。
具体在partition里面,会迭代数据生成新的iterator,是ByteBuffer构成的array,对于每一个列都会变成array的一部分,在遍历没一行数据的时候,都会变成列,每一列数据都会存入byteBuffer,
最后仍是会调用rdd的persist。
这个看起来有点像高性能的内存数据库,在进行表的查询时,把内存数据结构的分区进行具体的扫描操做,根据查询表达式创建索引,经过扫描器accessor得到具体的数据。
Catalyst支持让咱们本身采用udf、udaf的方式去扩展功能,catalyst在分析的时候,会支持这方面的功能,由functionRegistry来进行管理。
能够看到FunctionRegistry中主要是一些管理类方法。
到此,Catalyst中比较重要的功能都已解析完毕。
DT大数据天天晚上20:00YY频道现场授课频道68917580