SPARKSQL3.0-Catalog源码剖析

news2024/11/26 10:43:59

SPARKSQL3.0-Catalog源码剖析

一、前言

阅读本节需要先掌握Analyzer阶段的相关知识

在Spark SQL 系统中,Catalog 主要用于各种函数资源信息和元数据信息 (数据库、数据表数据视图、数据分区等)的统一管理。

初次看这种解释还是比较模糊,一会我们看源码就很清晰了

二、源码

首先Catalog是在SessionState类中,看过SessionState一节的话应该知道SessionState是在BaseSessionStateBuilder类中的build函数构建的:

def build(): SessionState = {
    new SessionState(
      session.sharedState,
      conf,
      experimentalMethods,
      functionRegistry,
      udfRegistration,
      () => catalog,		// 构建catalog
      sqlParser,
      () => analyzer,
      () => optimizer,
      planner,
      () => streamingQueryManager,
      listenerManager,
      () => resourceLoader,
      createQueryExecution,
      createClone,
      columnarRules)
  }

// 构建catalog
protected lazy val catalog: SessionCatalog = {
    val catalog = new SessionCatalog(
      () => session.sharedState.externalCatalog,
      () => session.sharedState.globalTempViewManager,
      functionRegistry,
      conf,
      SessionState.newHadoopConf(session.sparkContext.hadoopConfiguration, conf),
      sqlParser,
      resourceLoader)
    parentState.foreach(_.catalog.copyStateTo(catalog))
    catalog
  }

回顾一下:由于BaseSessionStateBuilder有两个子类分别是:HiveSessionStateBuilder、SessionStateBuilder;

所以决定构建哪个builder关键在于构建SparkSession时是否使用了enableHiveSupport函数,这里我们主要讲有关hive的HiveSessionStateBuilder,SessionStateBuilder不做介绍;

image-20221103115454870

父类BaseSessionStateBuilder的catalog函数在子类HiveSessionStateBuilder中被覆盖,故看子类HiveSessionStateBuilder的catalog函数:

image-20221103115610418

可以看到此处创建的catalog是HiveSessionCatalog【是SessionCatalog的子类】,这里放一张catalog的类图:

如果使用hive则创建HiveSessionCatalog

image-20221103115704923

这里简单介绍一下HiveSessionCatalog的属性:

class HiveSessionCatalog(
    externalCatalogBuilder: () => ExternalCatalog,
    globalTempViewManagerBuilder: () => GlobalTempViewManager,
    val metastoreCatalog: HiveMetastoreCatalog,
    functionRegistry: FunctionRegistry,
    conf: SQLConf,
    hadoopConf: Configuration,
    parser: ParserInterface,
    functionResourceLoader: FunctionResourceLoader)

1. externalCatalogBuilder【重要】:(外部系统的Catalog ):用来管理外部数据库(Databases )、数据 (Tables )、数据分区( Partitions )和函数(Functions )的接口;顾名思义其目标是与外部系统交互。
2. globalTempViewManagerBuilder:全局的临时视图管理,对应 DataFrame 中常用的 createGlobalTempView 方法,进行跨 Session 的视图管理
3. metastoreCatalog:用于与配置单元元存储交互的旧目录,将来将取消此类,统一使用externalCatalogBuilder对外交互
4. functionRegistry:函数注册接口,用来实现对函数的注册 Register 、查找( Lookup )和删除Drop 等功能。
5. xxxconf:相关配置类
6. functionResourceLoader:函数资源加载器:在 SparkSQL 中除内置实现的各种函数外,还支持用户自定义的函数和 Hive 中的各种函数

通过以上属性的介绍,再看关于catalog的定义:Catalog 主要用子各种元数资源信息和元数据信息 (数据库、数据表数据视图、数据分区与函数等)的统一管理;感觉是不是清晰了一些

在上面众多属性中最重要的是:externalCatalogBuilder,下面将着重介绍它;

先来看一下它的构建过程:可以看到是通过session.sharedState.externalCatalog构建出来的

image-20221103122409070

这里进入到ShareState类中,贴一下源码:可以看到是根据hive的属性值来确定最终会构建HiveExternalCatalog

lazy val externalCatalog: ExternalCatalogWithListener = {
  	// 这里是通过externalCatalogClassName函数获取到要反射的类名,然后通过reflect函数反射获取到externalCatalog
    val externalCatalog = SharedState.reflect[ExternalCatalog, SparkConf, Configuration](
      SharedState.externalCatalogClassName(conf), conf, hadoopConf)

    // 默认数据库default相关配置
    val defaultDbDefinition = CatalogDatabase(
      SessionCatalog.DEFAULT_DATABASE,
      "default database",
      CatalogUtils.stringToURI(conf.get(WAREHOUSE_PATH)),
      Map())

	  // 这里就是如果连接不上hive,会在默认目录下构建default数据库
    if (!externalCatalog.databaseExists(SessionCatalog.DEFAULT_DATABASE)) {
      externalCatalog.createDatabase(defaultDbDefinition, ignoreIfExists = true)
    }

    // Wrap to provide catalog events
    val wrapped = new ExternalCatalogWithListener(externalCatalog)

    // spark的事件总线,暂不关注
    wrapped.addListener((event: ExternalCatalogEvent) => sparkContext.listenerBus.post(event))

    wrapped
  }


private val HIVE_EXTERNAL_CATALOG_CLASS_NAME = "org.apache.spark.sql.hive.HiveExternalCatalog"


// 可以看到和SessionState构建的方式一样,关键在于构建SparkSession时是否使用了enableHiveSupport函数
// 如果使用了enableHiveSupport,则CATALOG_IMPLEMENTATION = hive ,即此处会构建HiveExternalCatalog
private def externalCatalogClassName(conf: SparkConf): String = {
    conf.get(CATALOG_IMPLEMENTATION) match {
      case "hive" => HIVE_EXTERNAL_CATALOG_CLASS_NAME
      case "in-memory" => classOf[InMemoryCatalog].getCanonicalName
    }
  }

这里放一张HiveExternalCatalog相关类图:可以看到统一父类的接口是ExternalCatalog,如果非hive,则会生成InMemoryCatalog

image-20221103123007661

这里我们再看一下HiveExternalCatalog实现的函数:可以看出对hive的DDL、DML操作都在这个类中

image-20221103123152534

在该类中大部分函数的操作都是使用内部的HiveClient【重要】:这是HiveClient接口,其实现类为HiveClientImpl

image-20221103123338523

image-20221103123502199

而在HiveClientImpl类中同样有一个shim变量,该变量便是spark兼容不同版本hive的关键所在:其内部实现较为巧妙,是将各个函数名称作为抽象函数,再由不同的版本的子类实现函数反射参数名称和入参类型,感兴趣的小伙伴可以跟进去看看

image-20221103123849760

HiveClientImpl内部提供了各种DML/DDL的实现,我们随便看一个dropTable函数:都是使用shim引用进行操作

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EnCWa1o3-1669097347665)(/Users/hzxt/Library/Application Support/typora-user-images/image-20221103123942870.png)]

再来看一下该类中的import引用:都是hive的原生包引用,至此可以很清楚的知道spark中对hive元数据的操作几乎都是通过hive原生包所提供的API

image-20221103124238323

至此catalog中的externalCatalog介绍完毕,其余属性感兴趣的小伙伴可以对照源码观看

**这里再介绍一个Analyzer阶段中hive表解析规则ResolveTables,如果没看过Analyzer阶段,建议先看完Analyzer阶段:https://blog.csdn.net/qq_35128600/article/details/127970299 **

当我们在执行一个sql = select 字段 from table时,Analyzer阶段会通过catalog来确定表是否存在以及获取表字段等相关属性,这个步骤是由解析表数据规则:ResolveTables实现的

点进去看到apply函数有模式匹配,这里我们以UnresolvedTable【未解析表】为节点类型,随后执行CatalogV2Util.loadTable(catalog, ident)函数

这里又调用了catalog.asTableCatalog.loadTable(ident)

这里来到了TableCatalog.loadTable,根据下面的结构知道这里会有几个子类,具体执行的其实是V2SessionCatalog

image-20221104112020369

我们可以简单做个debug测试验证一下,如下我们写一个sql然后执行

image-20221104112229320

在V2SessionCatalog中看到调用catalog.getTableMetadata,此处走到了SessionCatalog,如下图

在catalog.getTableMetadata函数中执行了externalCatalog.getTable(db, table)

这里看到externalCatalog就比较亲切了,假设我们是连接hive的session,则此时会走HiveExternalCatalog的getTable函数:

image-20220705153134372

image-20221104112434149

HiveExternalCatalog的getTable调用了restoreTableMetadata函数,此函数将会访问hive的metastore获取此表的元数据信息并构建出CatalogTable实体类返回

image-20220705153317645

我们再回到ResolveTables规则中,如下图

image-20220705153837909

至此spark的catalog的介绍以及Analyzer阶段中的简单使用结束

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/27564.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

5周年,时过境迁,千变万化

2022年11月22日 小雪 长沙 阴小雨 下午 吃饭 遇雨 跑 不知不觉开始博客5年啦,注册账号有6年了。 ~~~那就浅写一首不像诗的诗聊表纪念吧~~~ 其实偶尔还是会迷茫, 但不必过分紧张, 每个时代都有每个时代化的特色的机遇与挑战, …

服务案例|AI算法在Oracle指标异常检查、故障预测之牛刀小试

LinkSLA与南京大学合作,将AI算法引入运维平台,将趋势性、周期性强的指标数据通过机器学习,实现异常检测、故障预测等功能。 下面分享一个通过AI算法,对Oracle数据库故障预测的案例。 在3月16日,MOC工程师接到某公司的…

中学数学教学参考杂志社中学数学教学参考编辑部2022年第27期目录

谈学论教 “平行四边形”章首课的教学思考 李斌; 1-3 高中数学课程中的函数教学 孔鑫辉; 3-4《中学数学教学参考》投稿:cn7kantougao163.com 对方程起始课教学的探究 梅琴; 5-7 注重师生互动,激活数学课堂 董启福; 8-9 例析高中数学体验教学法的…

RPC框架(一)——简易RPC

RPC介绍 RPC,Remote Procedure Call 即远程过程调用,远程过程调用其实对标的是本地过程调用 一个RPC框架要进行使用应该要具有如下的组件(功能) 从整体层次来看,一个RPC协议的框架应该具有三个层面: 服…

RSE2021/云检测:基于小波变换和连续多尺度空间注意的上下块深度网络云检测

RSE2021/云检测Deep network based on up and down blocks using wavelet transform and successive multi-scale spatial attention for cloud detection基于小波变换和连续多尺度空间注意的上下块深度网络云检测0.摘要1.概述2.方法3.背景4.实验数据5.我们的方法5.1.UD-NET5.1…

frp内网穿透

文章目录原理如果没有配置ssh,需要先配置ssh免密登录到pc内网穿透流程frp自启动frps自启动frpc自启动原理 1、在公网中转服务器上面搭建FRP服务器。同时,在内网服务器上面安装FRP客户端。 2、按照UP的FRP客户端配置文件进行说明。7000端口是FRP服务端开放…

tk跨境电商好做吗?有什么技巧吗?

最近tiktok大热,不少小伙伴都在蠢蠢欲动了,但他们都在担心tk跨境电商到底好不好做?有什么技巧没有?因为怕耗时耗力最后一场空。这里我们大家就来简单聊聊吧! tk跨境电商好做吗? 其实个人认为tk跨境电商现阶…

fork函数相关资源复制问题验证

前言 fork是什么?克隆当前的进程,然后创建一个子进程。本文分几个验证实例代码,主要是为解决验证一些小问题。 一 fork与文件描述符 fork之前打开一个文件的测试。 问题:fork之后,父进程关闭文件,子进程是…

14天学习训练营导师课程-Pygame学习笔记-Part1(环境准备)

14天学习训练营导师课程: 李宁《Python Pygame游戏开发入门与实战》 李宁《计算机视觉OpenCV Python项目实战》1 李宁《计算机视觉OpenCV Python项目实战》2 李宁《计算机视觉OpenCV Python项目实战》3 学习知识点 学习先从环境安装和配置开始: 环境安装…

微积分在金融投资的应用

目 录 摘 要 I ABSTRACT II 1绪论 1 1.1选题背景及意义 1 1.2国内外研究现状 1 1.3微积分发展概述 2 1.3.1微积分学的创立 2 1.3.2微积分诞生的重要意义 3 1.3.3微积分理论内容介绍 3 1.3研究主要内容 4 2微积分在金融投资中的应用 5 2.1导数在金融投资中的应用 5 2.1.1导数在金…

Springboot疫苗接种管理系统-JAVA.JSP【数据库设计、源码、开题报告】

摘 要 预防预接种工作实行网络信息化管理,是我国免疫规划工作发展的需要。接种信息实行网络信息化不仅是预防接种工作步入了一个新的台阶,更重要的是解决了多年疫苗接种过程种,免疫接种剂次不清,难以全程有效接种的问题&#xff…

SpringBoot + openFeign实现远程接口调用

SpringBoot服务之间通过openFeign实现远程接口调用 现在的微服务项目不少都使用的是springbootspring cloud构建的项目,微服务之间的调用都离不开feign来进行远程调用。那么我们一个服务需要调用第三方的服务的时候,我们常常可能使用httpclient或者rest…

正大国际期货:2022正大期货在国际市场热度不减的几点原因

2022年国际期货是金融行业重点关注的对象,从今年市场数据中可以看出,正大国际期货之所以还能一如既往领跑,每年交易量都在递增,和正大后台的实力雄厚,坚守合作互赢的理念重大相关,接下来重点说说正大国际越…

【ML-SVM案例学习】svm实现手写数字识别

文章目录前言一、源码分步解析1.引入库2. 设置属性防止中文乱码3.加载数字图片数据4.获取样本数量,并将图片数据格式化5.模型构建6.测试数据部分实际值和预测值获取7.进行图片展示8.把预测错的值的 x值 y值 和y的预测值取出9.通过enumerate,分别拿出x值 …

Java的三大特性之继承

封装详见:Java的三大特性之封装 多态详见:Java的三大特性之多态 1.认识继承 继承的本质是对某一批类的抽象,从而实现对显示世界更好的建模。 extends “扩展” 子类是父类的扩展,子类继承了父类,就会有父类的全部方法…

强推这款键盘利器(Keychron),这次我彻底入坑了

嗨喽,大家好。还记得我今年五月份的时候,发布了一篇关于自己使用键盘的文章——>程序猿必备键盘推荐(Keychron),实用炫酷两不误,这篇文章发布后引起了强烈的反响。身边的同学、朋友,包括一些…

Ubuntu20.4系统隐藏顶栏

注:Ubuntu20.4以上版本安装gnome-tweak-tool可以实现隐藏顶栏了,但20.4还需要安装一下扩展模块,教程如下: 在Ubuntu中有两个扩展工具都支持隐藏顶栏。 1、安装autohidetopbar。 sudo apt install gnome-shell-extension-autohid…

【web】JavaScript——Web APIs笔记小结 dom 样式属性(自定义属性+节点操作部分)

期中考完回来更新了 感觉进度真的好慢T^T,已经摸了快一个月的鱼了qwq!!! 来源:JavaScript基础语法-dom-bom-js-es6新语法-jQuery-数据可视化echarts 目录 ⑦H5自定义属性 V.节点操作 ①节点层级 ※※父级节点 ※…

react事件系统(新老版本)

带着问题阅读探索 React 为什么有自己的事件系统?什么是事件合成 ?如何实现的批量更新?事件系统如何模拟冒泡和捕获阶段?如何通过 dom 元素找到与之匹配的fiber?为什么不能用 return false 来阻止事件的默认行为&…

SpringCloudGateway--自动路由映射

目录 一、GateWay项目创建 二、子项目创建 三、测试调用 一、GateWay项目创建 首先启动本地nacos&#xff0c;具体可参考&#xff1a;Nacos Windows安装_雨欲语的博客-CSDN博客 新建工程项目spring_cloud_test,pom引入依赖&#xff1a; <parent><groupId>org.s…