本文节选自清华大学出版社出版的图书《数据资产管理核心技术与应用》,作者为张永清等著。

从Spark 执行计划中获取数据血缘

因为数据处理任务会涉及到数据的转换和处理,所以从数据任务中解析血缘也是获取数据血缘的渠道之一,Spark 是大数据中数据处理最常用的一个技术组件,既可以做实时任务的处理,也可以做离线任务的处理。Spark在执行每一条SQL语句的时候,都会生成一个执行计划,这一点和很多数据库的做法很类似,都是SQL语句在执行时,先生成执行计划。如下图3-1-10所示,在Spark的官方文档链接https://spark.apache.org/docs/latest/sql-ref-syntax-qry-explain.html#content中,有明确提到,可以根据EXPLAIN关键字来获取执行计划,这和很多数据库查看执行计划的方式很类似。

图3-1-10

Spark底层生成执行计划以及处理执行计划的过程如下图3-1-11所示。本文节选自清华大学出版社出版的图书《数据资产管理核心技术与应用》,作者为张永清等著。

图3-1-11

从图中可以看到,

1、 执行SQL语句或者Data Frame时,会先生成一个Unresolved Logical Plan,就是没有做过任何处理和分析的逻辑执行计划,仅仅会从SQL语法的角度做一些基础性的校验。

2、 之后通过获取Catalog的数据,对需要执行的SQL语句做表名、列名的进一步分析校验,从而生成一个可以直接运行的逻辑执行计划。

3、 但是Spark底层会有个优化器来生成一个最优的执行操作方式,从而生成一个优化后的最佳逻辑执行计划。

4、 将最终确定下来的逻辑执行计划转换为物理执行计划,转换为最终的代码进行执行。

Spark的执行计划其实就是数据处理的过程计划,会将SQL语句或者DataFrame 做解析,并且结合Catalog一起,生成最终数据转换和处理的代码。所以可以从Spark的执行计划中,获取到数据的转换逻辑,从而解析到数据的血缘。但是spark的执行计划都是在spark底层内部自动处理的,如何获取到每次Spark任务的执行计划的信息呢?其实在Spark底层有一套Listener的架构设计,可以通过Spark Listener 来获取到spark 底层很多执行的数据信息。

在spark的源码中,以Scala的形式提供了一个org.apache.spark.sql.util.QueryExecutionListener  trait (类似Java 语言的接口),来作为Spark SQL等任务执行的监听器。在org.apache.spark.sql.util.QueryExecutionListener  中提供了如下表3-1-2所示的两个方法。

表3-1-2

方法名

描述

def onSuccess(funcName: String, qe: QueryExecution, durationNs: Long): Unit

执行成功时,调用的方法,其中包括了执行计划参数,这里的执行计划可以是逻辑计划或者物理计划

def onFailure(funcName: String, qe: QueryExecution, exception: Exception): Unit

执行失败时,调用的方法,其中同样也包括了执行计划参数,这里的执行计划可以是逻辑计划或者物理计划

因此可以借用QueryExecutionListener  来主动让Spark在执行任务时,将执行计划信息推送到自己的系统或者数据库中,然后再做进一步的解析,如下图3-1-12所示。本文节选自清华大学出版社出版的图书《数据资产管理核心技术与应用》,作者为张永清等著。

图3-1-12

import org.apache.spark.internal.Logging
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.execution.QueryExecution
import org.apache.spark.sql.util.QueryExecutionListener
case class PlanExecutionListener(sparkSession: SparkSession) extends QueryExecutionListener with Logging{ override def onSuccess(funcName: String, qe: QueryExecution, durationNs: Long): Unit = withErrorHandling(qe) {
// 执行成功时,调用解析执行计划的方法
planParser(qe)
} override def onFailure(funcName: String, qe: QueryExecution, exception: Exception): Unit = withErrorHandling(qe) { } private def withErrorHandling(qe: QueryExecution)(body: => Unit): Unit = {
try
body
catch {
case NonFatal(e) =>
val ctx = qe.sparkSession.sparkContext
logError(s"Unexpected error occurred during lineage processing for application: ${ctx.appName} #${ctx.applicationId}", e)
}
} def planParser(qe: QueryExecution): Unit = {
logInfo("----------- start to get spark analyzed LogicPlan--------")
//解析执行计划,并且将执行计划的数据发送到自有的系统或者数据库中
......
}
}

上面的代码中,实现了QueryExecutionListener 这个trait中的onSuccess和onFailure这两个方法,只有在onSuccess时,才需要获取执行计划的数据,因为只有onSuccess时的血缘才是有效的。

实现好了自定义的QueryExecutionListener后,可以通过sparkSession.listenerManager.register来将自己实现的PlanExecutionListener 注册到Spark会话中,listenerManager是Spark中Listener的管理器。

在获取到执行计划时,需要再结合Catalog一起,来进一步解析血缘的数据,如下图3-1-13所示

图3-1-13

Spark 中常见的执行计划实现类如下表3-1-3所示,获取数据血缘时,就是需要从如下的这些执行计划中解析血缘关系。本文节选自清华大学出版社出版的图书《数据资产管理核心技术与应用》,作者为张永清等著。

表3-1-3

执行计划实现类

描述

org.apache.spark.sql.execution.datasources.LogicalRelation

一般用于解析字段级的关联关系

org.apache.spark.sql.catalyst.catalog.HiveTableRelation

Hive 表关联关系的执行计划,一般用于SQL执行时,存在关联查询的情况会出现该执行计划。

org.apache.spark.sql.hive.execution.InsertIntoHiveTable

一般是在执行insert into 的SQL 语句时才会产生的执行计划,例如insert into xxx_table(colum1,column2) values("4","zhangsan")

org.apache.spark.sql.execution.datasources

.InsertIntoHadoopFsRelationCommand

一般用于执行类似    sparkSession

.read

.table("xx_source_table ")

.limit(10)

.write

.mode(SaveMode.Append)

.insertInto("xx_target_table ")产生的执行计划。

org.apache.spark.sql.hive.execution.

CreateHiveTableAsSelectCommand

一般是在执行create table xxx_table as的SQL 语句时才会产生的执行计划,例如create table xx_target_table as select * from xx_source_table

org.apache.spark.sql.execution.command

.CreateDataSourceTableAsSelectCommand

一般用于执行类似sparkSession

.read

.table("xx_source_table")

.limit(10)

.write

.mode(SaveMode.Append)

.saveAsTable("xx_target_table")产生的执行计划。

org.apache.spark.sql.execution.datasources

.InsertIntoDataSourceCommand

一般用于将SQL查询结果写入到一张表中,比如insert into xxx_target_table select * from xxx_source_table

如下是以org.apache.spark.sql.execution.datasources

.InsertIntoHadoopFsRelationCommand 为例的spark 执行计划的数据,如下数据已经将原始的执行计划转换为了json格式的数据,方便做展示。

.................更多内容,请参考清华大学出版社出版的图书《数据资产管理核心技术与应用》,作者为张永清等著

图书《数据资产管理核心技术与应用》核心章节节选-3.1.2. 从Spark 执行计划中获取数据血缘的更多相关文章

  1. 2、 Spark Streaming方式从socket中获取数据进行简单单词统计

    Spark 1.5.2 Spark Streaming 学习笔记和编程练习 Overview 概述 Spark Streaming is an extension of the core Spark ...

  2. Thymeleaf+SpringMVC,如何从模板中获取数据

    Thymeleaf+SpringMVC,如何从模板中获取数据 在一个典型的SpringMVC应用中,带@Controller注解的类负责准备数据模型Map的数据和选择一个视图进行渲染.这个模型Map对 ...

  3. hive从查询中获取数据插入到表或动态分区

    Hive的insert语句能够从查询语句中获取数据,并同时将数据Load到目标表中.现在假定有一个已有数据的表staged_employees(雇员信息全量表),所属国家cnty和所属州st是该表的两 ...

  4. 哪种方式更适合在React中获取数据?

    作者:Dmitri Pavlutin 译者:小维FE 原文:dmitripavlutin.com 国外文章,笔者采用意译的方式,以保证文章的可读性. 当执行像数据获取这样的I/O操作时,你必须发起获取 ...

  5. Django Form 实时从数据库中获取数据

    修改 models.py 添加 class UserType(models.Model): caption = models.CharField(max_length=32) 执行命令,生成数据库 p ...

  6. SpringMVC从Request域中获取数据

    SpringMVC从Request域中获取数据的三种方式 SpringMVC环境自行搭建, 约定存在如下目录和文件:/WEB-INF/pages/success.jsp 方式一:传入Model对象 前 ...

  7. Spark读取Hbase中的数据

    大家可能都知道很熟悉Spark的两种常见的数据读取方式(存放到RDD中):(1).调用parallelize函数直接从集合中获取数据,并存入RDD中:Java版本如下: JavaRDD<Inte ...

  8. 使用spark将内存中的数据写入到hive表中

    使用spark将内存中的数据写入到hive表中 hive-site.xml <?xml version="1.0" encoding="UTF-8" st ...

  9. SQL语句的使用,SELECT - 从数据库表中获取数据 UPDATE - 更新数据库表中的数据 DELETE - 从数据库表中删除数据 INSERT INTO - 向数据库表中插入数据

    SQL DML 和 DDL 可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL). SQL (结构化查询语言)是用于执行查询的语法. 但是 SQL 语言也包含用于更新. ...

  10. 解决在IE中获取数据的缓存问题,运行环境为node.js

    IE下默认会开启缓存策略,不管是页面还是通过ajax请求的数据都会议一个url,url是uri(统一资源定位符)的实例,url就是资源的标识符. 写一个demo进行验证,测试环境:IE8,node.j ...

随机推荐

  1. MySQL 存储函数及调用

    1.mysql 存储函数及调用 在MySQL中,存储函数(Stored Function)是一种在数据库中定义的特殊类型的函数,它可以从一个或多个参数返回一个值.存储函数在数据库层面上封装了复杂的SQ ...

  2. 打开TLS 1.1和1.2而不影响其他协议

    打开TLS 1.1和1.2而不影响其他协议 System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 ...

  3. ColorEasyDuino上手指南

    介绍 ColorEasyDuino是嘉立创推出的一块Aduino开发板(类似物),具有丰富的外设接口:uart.i2c.spi.adc.pwm等:开发板设计参考原型是Arduino Uno,采用的芯片 ...

  4. javascript高级编程笔记第五章

    chapter 5 5.5 Function类型 未完待续 函数实际上是对象,每个函数都是Function类型的实例,因此与其他引用类型一样具有属性和方法 因此函数名实际上就是函数对象的指针,不会与某 ...

  5. 聊一聊 Monitor.Wait 和 Pluse 的底层玩法

    一:背景 1. 讲故事 在dump分析的过程中经常会看到很多线程卡在Monitor.Wait方法上,曾经也有不少人问我为什么用 !syncblk 看不到 Monitor.Wait 上的锁信息,刚好昨天 ...

  6. EthernetIP IO从站设备数据 转opc ua项目案例

    1 案例说明 设置网关采集EthernetIP IO设备数据 把采集的数据转成opc ua协议转发给其他系统. 2 VFBOX网关工作原理 VFBOX网关是协议转换网关,是把一种协议转换成另外一种协议 ...

  7. Android 耳机驱动知识

    Android 耳机驱动知识 2015-03-06 工作以后接手的第一个驱动就是android平台下耳机的插拔检测和按键检测.这部分涉及的硬件知识比较简单,但是软件上对中断的处理,软件检测的鲁棒性,都 ...

  8. Linux设备模型:4、sysfs

    作者:wowo 发布于:2014-3-14 18:31 分类:统一设备模型 http://www.wowotech.net/device_model/dm_sysfs.html 前言 sysfs是一个 ...

  9. Maven的依赖详解和打包方式

    设置maven maven下载与安装教程: https://blog.csdn.net/YOL888666/article/details/122008374 1. 在File->setting ...

  10. 树莓派4B-控制霍尔编码器

    霍尔编码器-直流减速电机 介绍 直流减速电机,即齿轮减速电机,是在普通直流电机的基础上,加上配套齿轮减速箱.齿轮减速箱的作用是,提供较低的转速,较大的力矩.同时,齿轮箱不同的减速比可以提供不同的转速和 ...