SparkSql序列化时列的ID是在哪里生成的呢?

2022-11-25 19:55:33 浏览数 (1)

面向群友写文,哈哈

有点抽象,但群友们一定知道我在写什么

(原谅我,喜欢晒截图)

分享课上没有trace详细代码,这篇顺一下这块的代码。

sparksql生成解析后的逻辑执行计划时,会通过catalog把各个字段和元数据库绑定,也就说在ResolveLogical的阶段的字段是带了id的:

代码语言:javascript复制
SELECT A,B FROM TESTDATA2

==  Parsed Logical Plan  ==
'Project ['A, 'B]
 - 'UnresolvedRelation [TESTDATA2], [], false

== Analyzed Logical Plan ==
Project [A#3, B#4]
 - SubqueryAlias testdata2
    - View (`testData2`, [a#3,b#4])
       - SerializeFromObject [knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).a AS a#3, knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).b AS b#4]
          - ExternalRDD [obj#2]

可以看到从未解析到解析,字段由'Project ['A, 'B] --> Project [A#3, B#4]

那这个id是什么时候生成的呢?

id是在建表时或者创建临时视图时生成的。

我们以createOrReplaceTempView为例来看一下:

准备TESTDATA2测试数据时的逻辑——

1、SQLTestData 类中,生成testData2

2、SQLImplicits隐式转换把rdd转成DataSet

3、SQLImplicits 类的执行流程

SQLImplicits --> LowPrioritySQLImplicits -->newProductEncoder -->Encoders.product[T] --> ExpressionEncoder

下面图按顺序:

从上图可知会用到ExpressionEncoder类

4、ExpressionEncoder类的运行流程

sparksql源码中有很多操作是初始化类的时候做的

ExpressionEncoder.apply 这里计算:

代码语言:javascript复制
val serializer = ScalaReflection.serializerForType(tpe)
val deserializer = ScalaReflection.deserializerForType(tpe)

--> new ExpressionEncoder[T](serializer, deserializer, ClassTag[T](cls))

--> ExpressionEncoder.serializer (序列化操作)

-->CreateNamedStruct.flatten(匹配到If的分支调用CreateNamedStruct.flatten)

-->Alias(v, n.toString)(起别名)

-->exprId = NamedExpression.newExprId(ExprId就是序列化的id)

--> ExprId(curId.getAndIncrement(), jvmId)(序列化的id最终生成)

代码流程如下截图:

下篇写写createOrReplaceTempView的运行原理~

0 人点赞